HTTPServer在整个框架中最主要的作用是做TCP层和应用层之间的隔离,为IO和具体应用层搭建了桥梁。
响应流程图:
从功能上看,它最主要做的事情通俗的讲就是监听端口上的动静(主要是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)
还记得这个例子么:
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()