zoukankan      html  css  js  c++  java
  • django的web server的源代码流程

     1 class WSGIServer(simple_server.WSGIServer):
     2     """BaseHTTPServer that implements the Python WSGI protocol"""
     3 
     4     request_queue_size = 10
     5 
     6     def __init__(self, *args, ipv6=False, allow_reuse_address=True, **kwargs):
     7         if ipv6:
     8             self.address_family = socket.AF_INET6
     9         self.allow_reuse_address = allow_reuse_address
    10         super().__init__(*args, **kwargs)
    11 
    12     def handle_error(self, request, client_address):
    13         if is_broken_pipe_error():
    14             logger.info("- Broken pipe from %s
    ", client_address)
    15         else:
    16             super().handle_error(request, client_address)
    17 
    18 class WSGIRequestHandler(simple_server.WSGIRequestHandler):
    19     protocol_version = 'HTTP/1.1'
    20 
    21     def address_string(self):
    22         # Short-circuit parent method to not call socket.getfqdn
    23         return self.client_address[0]
    24 
    25     def log_message(self, format, *args):
    26         extra = {
    27             'request': self.request,
    28             'server_time': self.log_date_time_string(),
    29         }
    30         if args[1][0] == '4':
    31             # 0x16 = Handshake, 0x03 = SSL 3.0 or TLS 1.x
    32             if args[0].startswith('x16x03'):
    33                 extra['status_code'] = 500
    34                 logger.error(
    35                     "You're accessing the development server over HTTPS, but "
    36                     "it only supports HTTP.
    ", extra=extra,
    37                 )
    38                 return
    39 
    40         if args[1].isdigit() and len(args[1]) == 3:
    41             status_code = int(args[1])
    42             extra['status_code'] = status_code
    43 
    44             if status_code >= 500:
    45                 level = logger.error
    46             elif status_code >= 400:
    47                 level = logger.warning
    48             else:
    49                 level = logger.info
    50         else:
    51             level = logger.info
    52 
    53         level(format, *args, extra=extra)
    54 
    55     def get_environ(self):
    56         # Strip all headers with underscores in the name before constructing
    57         # the WSGI environ. This prevents header-spoofing based on ambiguity
    58         # between underscores and dashes both normalized to underscores in WSGI
    59         # env vars. Nginx and Apache 2.4+ both do this as well.
    60         for k in self.headers:
    61             if '_' in k:
    62                 del self.headers[k]
    63 
    64         return super().get_environ()
    65 
    66     def handle(self):
    67         self.close_connection = True
    68         self.handle_one_request()
    69         while not self.close_connection:
    70             self.handle_one_request()
    71         try:
    72             self.connection.shutdown(socket.SHUT_WR)
    73         except (socket.error, AttributeError):
    74             pass
    75 
    76     def handle_one_request(self):
    77         """Copy of WSGIRequestHandler.handle() but with different ServerHandler"""
    78         self.raw_requestline = self.rfile.readline(65537)
    79         if len(self.raw_requestline) > 65536:
    80             self.requestline = ''
    81             self.request_version = ''
    82             self.command = ''
    83             self.send_error(414)
    84             return
    85 
    86         if not self.parse_request():  # An error code has been sent, just exit
    87             return
    88 
    89         handler = ServerHandler(
    90             self.rfile, self.wfile, self.get_stderr(), self.get_environ()
    91         )
    92         handler.request_handler = self      # backpointer for logging & connection closing
    93         handler.run(self.server.get_app())
    WSGIServer的父类是wsgiref.simple_server.WSGIServer, wsgiref.simple_server.WSGIServer的父类是http.server.HTTPServer,http.server.HTTPServer的父类是socketserver.TCPServer;
    WSGIRequestHandler的父类是wsgiref.simple_server.WSGIRequestHandler,wsgiref.simple_server.WSGIRequestHandler的父类是http.server.BaseHTTPRequestHandler,
    http.server.BaseHTTPRequestHandler的父类是socketserver.StreamRequestHandler,socketserver.StreamRequestHandler的父类是socketserver.BaseRequestHandler
    def run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer):
        server_address = (addr, port)
        if threading:
            httpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), {})
        else:
            httpd_cls = server_cls
        httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)  实例化WSGIserver
        if threading:
            # ThreadingMixIn.daemon_threads indicates how threads will behave on an
            # abrupt shutdown; like quitting the server by the user or restarting
            # by the auto-reloader. True means the server will not wait for thread
            # termination before it quits. This will make auto-reloader faster
            # and will prevent the need to kill the server manually if a thread
            # isn't terminating correctly.
            httpd.daemon_threads = True
        httpd.set_app(wsgi_handler)
        httpd.serve_forever()  #这里调用TCPserver的父类BaseServer的serve_forever方法

    在socketserver.BaseServer.serve_forever中

     1     def serve_forever(self, poll_interval=0.5):
     2         """Handle one request at a time until shutdown.
     3 
     4         Polls for shutdown every poll_interval seconds. Ignores
     5         self.timeout. If you need to do periodic tasks, do them in
     6         another thread.
     7         """
     8         self.__is_shut_down.clear()
     9         try:
    10             # XXX: Consider using another file descriptor or connecting to the
    11             # socket to wake this up instead of polling. Polling reduces our
    12             # responsiveness to a shutdown request and wastes cpu at all other
    13             # times.
    14             with _ServerSelector() as selector:
    15                 selector.register(self, selectors.EVENT_READ)
    16 
    17                 while not self.__shutdown_request:
    18                     ready = selector.select(poll_interval)
    19                     # bpo-35017: shutdown() called during select(), exit immediately.
    20                     if self.__shutdown_request:
    21                         break
    22                     if ready:
    23                         self._handle_request_noblock()  在这里调用process_request方法
    24 
    25                     self.service_actions()
    26         finally:
    27             self.__shutdown_request = False
    28             self.__is_shut_down.set()

    在process_request方法中调用finish_request方法去实例化WSGIRequestHandler

    1     def process_request(self, request, client_address):
    2         """Call finish_request.
    3 
    4         Overridden by ForkingMixIn and ThreadingMixIn.
    5 
    6         """
    7         self.finish_request(request, client_address)
    8         self.shutdown_request(request)

    在finish_request中实例化WSGIRequestHandler

        def finish_request(self, request, client_address):
            """Finish one request by instantiating RequestHandlerClass."""
            self.RequestHandlerClass(request, client_address, self)  #这个self是WSGIserver实例化的对象
    class BaseRequestHandler:  #实例化WSGIRequestHandler必须先初始化BaseRequestHandler类
    
        """Base class for request handler classes.
    
        This class is instantiated for each request to be handled.  The
        constructor sets the instance variables request, client_address
        and server, and then calls the handle() method.  To implement a
        specific service, all you need to do is to derive a class which
        defines a handle() method.
    
        The handle() method can find the request as self.request, the
        client address as self.client_address, and the server (in case it
        needs access to per-server information) as self.server.  Since a
        separate instance is created for each request, the handle() method
        can define other arbitrary instance variables.
    
        """
    
        def __init__(self, request, client_address, server):
            self.request = request
            self.client_address = client_address
            self.server = server
            self.setup()
            try:
                self.handle()  #这个类没有实现handle方法,所以需要从WSGIRequestHandler里面去找
            finally:
                self.finish()
    
        def setup(self):
            pass
    
        def handle(self):
            pass
    
        def finish(self):
            pass
    
    class StreamRequestHandler(BaseRequestHandler):
    
        """Define self.rfile and self.wfile for stream sockets."""
    
        # Default buffer sizes for rfile, wfile.
        # We default rfile to buffered because otherwise it could be
        # really slow for large data (a getc() call per byte); we make
        # wfile unbuffered because (a) often after a write() we want to
        # read and we need to flush the line; (b) big writes to unbuffered
        # files are typically optimized by stdio even when big reads
        # aren't.
        rbufsize = -1
        wbufsize = 0
    
        # A timeout to apply to the request socket, if not None.
        timeout = None
    
        # Disable nagle algorithm for this socket, if True.
        # Use only when wbufsize != 0, to avoid small packets.
        disable_nagle_algorithm = False
    
        def setup(self):
            self.connection = self.request
            if self.timeout is not None:
                self.connection.settimeout(self.timeout)
            if self.disable_nagle_algorithm:
                self.connection.setsockopt(socket.IPPROTO_TCP,
                                           socket.TCP_NODELAY, True)
            self.rfile = self.connection.makefile('rb', self.rbufsize)
            if self.wbufsize == 0:
                self.wfile = _SocketWriter(self.connection)
            else:
                self.wfile = self.connection.makefile('wb', self.wbufsize)
    
        def finish(self):
            if not self.wfile.closed:
                try:
                    self.wfile.flush()
                except socket.error:
                    # A final socket error may have occurred here, such as
                    # the local error ECONNABORTED.
                    pass
            self.wfile.close()
            self.rfile.close()

    在handle方法中

     1 class WSGIRequestHandler(BaseHTTPRequestHandler):
     2 
     3     server_version = "WSGIServer/" + __version__
     4 
     5     def get_environ(self):
     6         env = self.server.base_environ.copy()
     7         env['SERVER_PROTOCOL'] = self.request_version
     8         env['SERVER_SOFTWARE'] = self.server_version
     9         env['REQUEST_METHOD'] = self.command
    10         if '?' in self.path:
    11             path,query = self.path.split('?',1)
    12         else:
    13             path,query = self.path,''
    14 
    15         env['PATH_INFO'] = urllib.parse.unquote(path, 'iso-8859-1')
    16         env['QUERY_STRING'] = query
    17 
    18         host = self.address_string()
    19         if host != self.client_address[0]:
    20             env['REMOTE_HOST'] = host
    21         env['REMOTE_ADDR'] = self.client_address[0]
    22 
    23         if self.headers.get('content-type') is None:
    24             env['CONTENT_TYPE'] = self.headers.get_content_type()
    25         else:
    26             env['CONTENT_TYPE'] = self.headers['content-type']
    27 
    28         length = self.headers.get('content-length')
    29         if length:
    30             env['CONTENT_LENGTH'] = length
    31 
    32         for k, v in self.headers.items():
    33             k=k.replace('-','_').upper(); v=v.strip()
    34             if k in env:
    35                 continue                    # skip content length, type,etc.
    36             if 'HTTP_'+k in env:
    37                 env['HTTP_'+k] += ','+v     # comma-separate multiple headers
    38             else:
    39                 env['HTTP_'+k] = v
    40         return env
    41 
    42     def get_stderr(self):
    43         return sys.stderr
    44 
    45     def handle(self):
    46         """Handle a single HTTP request"""
    47 
    48         self.raw_requestline = self.rfile.readline(65537)  #读取游览器发来的请求包文起始
    49         if len(self.raw_requestline) > 65536:  #判断数据长度是否大于65536
    50             self.requestline = ''
    51             self.request_version = ''
    52             self.command = ''
    53             self.send_error(414)   #发送414错误
    54             return
    55 
    56         if not self.parse_request(): # An error code has been sent, just exit
    57             return
    58 
    59         handler = ServerHandler(
    60             self.rfile, self.wfile, self.get_stderr(), self.get_environ()
    61         )  #rfile相当于socket中的recv,wfile相当于socket中的send,   get_atderr是系统的标准错误输出句柄, get_environ是先将下划线开头的头部字段删除,再调用父类的get_envrion方法将请求的头部字段加上HTTP_,再添加一些公共字段
    62         handler.request_handler = self      # backpointer for logging
    63         handler.run(self.server.get_app())

    在run中

     1     def run(self, application):
     2         """Invoke the application"""
     3         # Note to self: don't move the close()!  Asynchronous servers shouldn't
     4         # call close() from finish_response(), so if you close() anywhere but
     5         # the double-error branch here, you'll break asynchronous servers by
     6         # prematurely closing.  Async servers must return from 'run()' without
     7         # closing if there might still be output to iterate over.
     8         try:
     9             self.setup_environ()  #设置环境,将系统环境拷贝,然后将传入的环境变量扩展进该环境内同时增加一些WSGI通用环境
    10             self.result = application(self.environ, self.start_response)#设置完环境后开始执行我们传入的handler对象
    11             self.finish_response()
    12         except:
    13             try:
    14                 self.handle_error()
    15             except:
    16                 # If we get an error handling an error, just give up already!
    17                 self.close()
    18                 raise   # ...and let the actual server figure it out.

    也就是执行以下代码

     1 class WSGIHandler(base.BaseHandler):
     2     request_class = WSGIRequest
     3 
     4     def __init__(self, *args, **kwargs):
     5         super(WSGIHandler, self).__init__(*args, **kwargs)
     6         self.load_middleware()
     7 
     8     def __call__(self, environ, start_response):
     9         set_script_prefix(get_script_name(environ))
    10         signals.request_started.send(sender=self.__class__, environ=environ)
    11         request = self.request_class(environ)
    12         response = self.get_response(request)
    13         response._handler_class = self.__class__
    14 
    15         status = '%d %s' % (response.status_code, response.reason_phrase)
    16         response_headers = [(str(k), str(v)) for k, v in response.items()]
    17         for c in response.cookies.values():
    18             response_headers.append((str('Set-Cookie'), str(c.output(header=''))))
    19         start_response(force_str(status), response_headers)
    20         if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
    21             response = environ['wsgi.file_wrapper'](response.file_to_stream)
    22         return response


  • 相关阅读:
    函数式宏定义与普通函数
    linux之sort用法
    HDU 4390 Number Sequence 容斥原理
    HDU 4407 Sum 容斥原理
    HDU 4059 The Boss on Mars 容斥原理
    UVA12653 Buses
    UVA 12651 Triangles
    UVA 10892
    HDU 4292 Food
    HDU 4288 Coder
  • 原文地址:https://www.cnblogs.com/arrow-kejin/p/10361341.html
Copyright © 2011-2022 走看看