调了好久的tornado接口,一直不知道收到请求后怎么就到了handler的get/post中处理请求,想看看源码长啥样。
下面是官方文档中的例程:
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
上面的例程首先定义了一个handler,然后将handler与url的对应关系送入application,生成一个application实例,最后在app.listen中将app实例送入httpserver,并开启ioloop。
Application
tornado.web.Application负责为请求指路。
在初始化时,application会接受一个从url到handler的路由表,application在收到请求后会根据路由表,启动相应的handler处理请求。
当请求到来时,httpserver会调用Application.__call__()
函数(还没看server,仅是猜测),这个函数接受一个请求,并根据请求找到相应的handler,最终调用这个handler的_execute函数。(下文再讲handler)
class Application(ReversibleRouter):
...
def __call__(self, request):
# Legacy HTTPServer interface
dispatcher = self.find_handler(request)
return dispatcher.execute()
上文中的self.find_handler(request)
层层调用和继承, 路径大概是下面这样,最终其实返回了一个名为handlerdelegate的类的实例。
Application.find_handler()
-->
_ApplicationRouter.find_handler(request)(继承至RuleRouter)
-->
_ApplicationRouter.get_target_delegate()(重写了RuleRouter中的get_target_delegate)
-->
Application.get_handler_delegate()
-->
_HandlerDelegate
相关源码:
class Application(ReversibleRouter):
def __init__(self,handlers=None,...)
...
self.default_router = _ApplicationRouter(...)
...
def find_handler(self, request, **kwargs):
route = self.default_router.find_handler(request)
if route is not None:
return route
def get_handler_delegate(self, ...):
return _HandlerDelegate(...)
class _ApplicationRouter(ReversibleRuleRouter):
...
def get_target_delegate(self, ...):
if isclass(target) and issubclass(target, RequestHandler):
return self.application.get_handler_delegate(request, target, **target_params)
return super(_ApplicationRouter, self).get_target_delegate(target, request, **target_params)
class ReversibleRuleRouter(ReversibleRouter, RuleRouter):
...
class RuleRouter(Router):
...
def find_handler(self, request, **kwargs):
...
delegate = self.get_target_delegate()
if delegate is not None:
return delegate
Application.find_handler()
中的dispatcher就是_HandlerDelegate的一个实例
dispatcher.execute()
最终会调用RequestHandler._execute().
这个函数才是收到请求后真正执行的函数。(下面的handler部分再详细说)
执行完之后会返回一个future对象。
_HandlerDelegate.execute()
-->
RequestHandler._execute()
相关源码
class _HandlerDelegate(httputil.HTTPMessageDelegate):
def execute(self):
...
if self.stream_request_body:
self.handler._prepared_future = Future()
self.handler._execute(transforms, *self.path_args,
**self.path_kwargs)
return self.handler._prepared_future
每次响应请求时,RequestHandler
都会调用Application
中的log_request
函数,就是这里才会使每次请求都记入日志。
access_log = logging.getLogger("tornado.access")
class Application(ReversibleRouter):
...
def log_request(self, handler):
"""Writes a completed HTTP request to the logs.
By default writes to the python root logger. To change
this behavior either subclass Application and override this method,
or pass a function in the application settings dictionary as
``log_function``.
"""
if "log_function" in self.settings:
self.settings["log_function"](handler)
return
if handler.get_status() < 400:
log_method = access_log.info
elif handler.get_status() < 500:
log_method = access_log.warning
else:
log_method = access_log.error
request_time = 1000.0 * handler.request.request_time()
log_method("%d %s %.2fms", handler.get_status(),
handler._request_summary(), request_time)
RequestHandler
所有处理请求的类都继承自RequestHandler
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
实际使用中需要自定义一个RequestHandler的子类。
如果自定义初始化,不能直接重写__init__()
,
取而代之的是重写initialize()
,
在RequestHandler的__init__
中最终会调用initialize()
.
class RequestHandler(object):
def __init__(self, application, request, **kwargs):
...
self.initialize(**kwargs)
def initialize(self):
pass
RequestHandler中写好了常用请求类型的接口,比如get,post,
需要在子类中重写对应类别的函数。
class RequestHandler(object):
...
def get(self, *args, **kwargs):
raise HTTPError(405)
def post(self, *args, **kwargs):
raise HTTPError(405)
def delete(self, *args, **kwargs):...
def patch(self, *args, **kwargs):...
def put(self, *args, **kwargs):...
def options(self, *args, **kwargs):...
上面提到,服务每次收到请求都会调用RequestHandler._execute()
这个函数会先调用prepare()
,如果需要在所有请求处理的开头都执行相同的步骤,可以重写这个方法。
_execute()
会调用我们重写的get/post之类的函数,将其命名为method
如果在子类中没有显式调用self.finish()
,程序将自动调用。
class RequestHandler(object):
...
def prepare(self):
pass
@gen.coroutine
def _execute(self, transforms, *args, **kwargs):
...
result = self.prepare()
...
method = getattr(self, self.request.method.lower())
result = method(*self.path_args, **self.path_kwargs)
...
if self._auto_finish and not self._finished:
self.finish()
finish
这个方法会将数据写入缓存并发送回客户端,
finish
最后调用on_finish()
,如果所有的子类都有共同的结束流程,可以重写这个函数,意思跟prepare()一样。
RequestHandler.finish()
不是一定要在handler结束时调用,可以提前调用,减少响应时间,调用之后可以在本地做其他事情
这个函数还会调用_log()
方法写入日志,_log()
函数实际调用的是Application中的log_request()
RequestHandler.finish()
长这样
class RequestHandler(object):
...
def on_finish(self):
pass
def finish(self, chunk=None):
"""Finishes this response, ending the HTTP request."""
if self._finished:
raise RuntimeError("finish() called twice")
if chunk is not None:
self.write(chunk)
...
self.flush(include_footers=True)
self.request.finish()
self._log()
self._finished = True
self.on_finish()
self._break_cycles()
有不对的地方请大家指正
网友评论