類HTTPServer

HTTPServer在整個框架中最主要的做用是作TCP層和應用層之間的隔離,爲IO和具體應用層搭建了橋樑。python

響應流程圖:web

從功能上看,它最主要作的事情通俗的講就是監聽端口上的動靜(主要是TCP層),當客戶端向服務器某個端口發起請求被其監聽到以後,經過handle_stream來作對應的處理,其中最終調用了HTTP1ServerConnection類的start_serving方法,在這個方法裏最終回調了HTTPServer實現的start_request接口,進入了_ServerRequestAdapter類,在此類初始化的時候判斷HTTPServer類裏的request_callback是否是一個HTTPServerConnectionDelegate(顯然不少時候咱們都定義其繼承類Application),是的話調用此delegate的start_request方法。
服務器

class HTTPServer(TCPServer, httputil.HTTPServerConnectionDelegate):
    def __init__(self, request_callback, no_keep_alive=False, io_loop=None,
                 xheaders=False, ssl_options=None, protocol=None,
                 decompress_request=False,
                 chunk_size=None, max_header_size=None,
                 idle_connection_timeout=None, body_timeout=None,
                 max_body_size=None, max_buffer_size=None):
        self.request_callback = request_callback
        #...

    def handle_stream(self, stream, address):
        context = _HTTPRequestContext(stream, address,
                                      self.protocol)
        conn = HTTP1ServerConnection(
            stream, self.conn_params, context)
        self._connections.add(conn)
        conn.start_serving(self)
    def start_request(self, server_conn, request_conn):
        return _ServerRequestAdapter(self, server_conn, request_conn)
        
##httpserver繼承TCPserver中的listen啓動監聽,在啓動過程當中綁定socket,當socket上出現新鏈接請求的時候,啓動handle_stream作對應處理
    def listen(self, port, address=""):
        sockets = bind_sockets(port, addrebind_socketsss=address)
        self.add_sockets(sockets)

    def add_sockets(self, sockets):  
        if self.io_loop is None:
            self.io_loop = IOLoop.current()
        for sock in sockets:
            self._sockets[sock.fileno()] = sock
            add_accept_handler(sock, self._handle_connection,  
                               io_loop=self.io_loop)
                               
    def _handle_connection(self, connection, address):
        #....
            self.handle_stream(stream, address)
            
##############class HTTP1ServerConnection(object):            
    def start_serving(self, delegate):
        assert isinstance(delegate, httputil.HTTPServerConnectionDelegate)
        self._serving_future = self._server_request_loop(delegate)
        self.stream.io_loop.add_future(self._serving_future,
                                       lambda f: f.result())

    @gen.coroutine
    def _server_request_loop(self, delegate):
       #...
                conn = HTTP1Connection(self.stream, False,
                                       self.params, self.context)
                request_delegate = delegate.start_request(self, conn)
               
###########真正將客戶端請求回調到對應的handler的地方               
class _ServerRequestAdapter(httputil.HTTPMessageDelegate):
    def __init__(self, server, server_conn, request_conn):
        #...
        if isinstance(server.request_callback,
                      httputil.HTTPServerConnectionDelegate):
            self.delegate = server.request_callback.start_request(
                server_conn, request_conn)


還記得這個例子麼:
app

if __name__=="__main__":
    tornado.options.parse_command_line()   
    
    #實例了一個Application,其中有兩個RequestHandler對:"/" -- IndexHandler,'/poem' -- PoemPageHandler
    app = tornado.web.Application(
        handlers=[(r"/", IndexHandler), (r'/poem', PoemPageHandler)],
        template_path=os.path.join(os.path.dirname(__file__), "templates")
    )
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

  用戶定義好了兩個RequestHandler,分別對應輸入流裏的」/「 和‘/poem‘,將此元組初始化Application,並將其做爲參數傳遞給http_server, http_server啓動監聽,當監聽到客戶端傳來的輸入流,截取其中的header,並將其轉入Application的start_request處理。框架

    def start_request(self, server_conn, request_conn):
        # Modern HTTPServer interface
        return _RequestDispatcher(self, request_conn)

###then 咱們來到這個具體實現的類:

class _RequestDispatcher(httputil.HTTPMessageDelegate):
    
    def headers_received(self, start_line, headers):
        self.set_request(httputil.HTTPServerRequest(
            connection=self.connection, start_line=start_line, headers=headers))
        if self.stream_request_body:
            self.request.body = Future()
            return self.execute()

    def _find_handler(self):    
        app = self.application
        handlers = app._get_host_handlers(self.request)
        if not handlers:
            self.handler_class = RedirectHandler
            self.handler_kwargs = dict(url="%s://%s/" % (self.request.protocol, app.default_host))
            return
        for spec in handlers:
            match = spec.regex.match(self.request.path)
            if match:
                self.handler_class = spec.handler_class
                self.handler_kwargs = spec.kwargs
                if spec.regex.groups:
                   
                    if spec.regex.groupindex:
                        self.path_kwargs = dict(
                            (str(k), _unquote_or_none(v))
                            for (k, v) in match.groupdict().items())
                    else:
                        self.path_args = [_unquote_or_none(s)
                                          for s in match.groups()]
                return
        if app.settings.get('default_handler_class'):
            self.handler_class = app.settings['default_handler_class']
            self.handler_kwargs = app.settings.get(
                'default_handler_args', {})
        else:
            self.handler_class = ErrorHandler
            self.handler_kwargs = dict(status_code=404)


    def execute(self):
   
        if not self.application.settings.get("compiled_template_cache", True):
            with RequestHandler._template_loader_lock:
                for loader in RequestHandler._template_loaders.values():
                    loader.reset()
        if not self.application.settings.get('static_hash_cache', True):
            StaticFileHandler.reset()

        self.handler = self.handler_class(self.application, self.request,
                                          **self.handler_kwargs)
        transforms = [t(self.request) for t in self.application.transforms]

        if self.stream_request_body:
            self.handler._prepared_future = Future()
相關文章
相關標籤/搜索