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


  • 相关阅读:
    CentOS6.3升级GCC到GCC4.8.2
    监督式学习 -- 分类决策树(一)
    DICOM医学图像处理:fo-dicom网络传输之 C-Echo and C-Store
    百度地图----->地图类型、定位模式、实时交通、我的位置、加入覆盖物、覆盖物详情及提示
    "浪潮杯"第六届ACM山东省省赛山科场总结
    标题栏风格设置
    ActionBarActivity设置全屏无标题
    王立平--自己定义TitleBar
    C++ const限定符
    黑马day14 过滤器概述&生命周期&运行过程
  • 原文地址:https://www.cnblogs.com/arrow-kejin/p/10361341.html
Copyright © 2011-2022 走看看