Flask源码解析(1)
flask app.py
首先,初始化Flask,绑定一些属性,得到一个flask app
然后调用app的run方法,call procedure如下:
run(flask.app) -> run_simple(werkzeug.serving) -> make_server(werkzeug.serving)
其中,run_simple中继续处理参数,make_server根据需要决定创建什么类型的server(多进程,多线程,etc)
假设创建的是BaseWSGIServer(werkzeug.serving),接下来,在make_server里会返回一个BaseWSGIServer实例
在werkzeug的serving模块,定义了各种Server,各个server的继承关系如下:
同时还有一个WSGIRequestHandler,继承自BaseHTTPRequestHandler,这个handler是用来处理各种请求的工具
创建完成server实例之后,调用实例的server_forever方法监听请求
之后call procedure如下:
serve_forever(werkzeug.serving) -> serve_forever(SocketServer.BaseServer) -> _eintr_retry(SocketServer.BaseServer) -> _handle_request_noblock(SocketServer.BaseServer)
这里停一下,_eintr_retry方法里使用了select监听请求,一旦有请求到来,则read file descriptor准备就绪,继续到_handle_request_noblock方法中处理请求
_handle_request_noblock这个方法比较重要,显示了请求的处理流程,如下所示:
def _handle_request_noblock(self): """Handle one request, without blocking. I assume that select.select has returned that the socket is readable before this function was called, so there should be no risk of blocking in get_request(). """ try: request, client_address = self.get_request() except socket.error: return if self.verify_request(request, client_address): try: self.process_request(request, client_address) except: self.handle_error(request, client_address) self.shutdown_request(request)
get_request方法如下:
def get_request(self): con, info = self.socket.accept() return con, info
大多数情况下,这里的socket是在BaseWSGIServer的父类(HTTPServer)的构造函数里初始化的:
self.socket = socket.socket(self.address_family,
self.socket_type)
当使用ssl_context的时候,socket要经过封装:
self.socket = ssl_context.wrap_socket(sock, server_side=True)
总之,get_request方法返回一个tuple,一个是connection,一个是remote client addr
print一下它们的类型如下:
<class 'socket._socketobject'> <type 'tuple'>
verify_request(SocketServer)方法可以自定义,默认返回True
process_request(SocketServer)方法如下:
def process_request(self, request, client_address): """Call finish_request. Overridden by ForkingMixIn and ThreadingMixIn. """ self.finish_request(request, client_address) self.shutdown_request(request)
finish_request(SocketServer)初始化了RequestHandlerClass类,这个类是之前指定的WSGIRequestHandler:
def finish_request(self, request, client_address): """Finish one request by instantiating RequestHandlerClass.""" self.RequestHandlerClass(request, client_address, self)
初始化WSGIRequestHandler要追溯到BaseRequestHandler里去,这个类的构造方法如下:
def __init__(self, request, client_address, server): self.request = request self.client_address = client_address self.server = server self.setup() # StreamRequestHandler try: self.handle() # WSGIRequestHandler finally: self.finish() # StreamRequestHandler
构造函数里各个方法对应的class已在注释里标明
按照流程应该解析这3个方法:
setup方法设置了socket的参数和读写流
handle方法是处理请求的核心,这个之后会详细说明
finish方法关闭Socket读写流
WSGIRequestHandler的handle方法如下:
def handle(self): """Handles a request ignoring dropped connections.""" rv = None try: rv = BaseHTTPRequestHandler.handle(self) except (socket.error, socket.timeout) as e: self.connection_dropped(e) except Exception: if self.server.ssl_context is None or not is_ssl_error(): raise if self.server.shutdown_signal: self.initiate_shutdown() return rv
调用的handle方法位于BaseHTTPRequestHandler,这个方法又反过来调用WSGIRequestHandler的handle_one_request方法:
def handle_one_request(self): """Handle a single HTTP request.""" self.raw_requestline = self.rfile.readline() if not self.raw_requestline: self.close_connection = 1 elif self.parse_request(): return self.run_wsgi()
显然,这个方法读取了请求信息,预处理了一下请求,然后调用了本类中的run_wsgi方法:
run_wsgi是一个较为核心的方法,它的实现遵循了WSGI规范,包含write,start_response,execute 3个子方法
这个方法先是构造了一个environ字典,将处理请求所需的参数填进去
然后调用execute方法,这个方法call了一下app:
application_iter = app(environ, start_response)
然后将返回的数据通过write方法写回client
call app之后发生的事情非常关键,接下来就进入请求阶段