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之后发生的事情非常关键,接下来就进入请求阶段

 

posted @ 2018-08-18 14:38  geeklove  阅读(280)  评论(0编辑  收藏  举报