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()