Flask接收请求的流程

Flask接收请求的流程

Flask是基于werkzeug包实现的。

来研究一下,request是如何通过werkzeug传递给Flask的。

同时研究一下BaseServerserve_forever

BaseWSGIServer

BaseWSGIServerwerkzeug的一个类,继承了HTTPServer
class BaseWSGIServer(HTTPServer)

首先查看构造函数

BaseWSGIServer__init__

    def __init__(
        self,
        host: str,
        port: int,
        app: "WSGIApplication",
        handler: t.Optional[t.Type[WSGIRequestHandler]] = None,
        passthrough_errors: bool = False,
        ssl_context: t.Optional[_TSSLContextArg] = None,
        fd: t.Optional[int] = None,
    ) -> None:
        # 默认
        if handler is None:
            handler = WSGIRequestHandler
        ...# 初始化

        super().__init__(server_address, handler)  # type: ignore

        self.app = app
        self.passthrough_errors = passthrough_errors
        self.shutdown_signal = False
        self.host = host
        self.port = self.socket.getsockname()[1]
		# 初始化
        ...

    def log(self, type: str, message: str, *args: t.Any) -> None:
        _log(type, message, *args)

    def serve_forever(self, poll_interval: float = 0.5) -> None:
        self.shutdown_signal = False
        try:
            super().serve_forever(poll_interval=poll_interval)
        except KeyboardInterrupt:
            pass
        finally:
            self.server_close()

    def handle_error(self, request: t.Any, client_address: t.Tuple[str, int]) -> None:
        if self.passthrough_errors:
            raise

        return super().handle_error(request, client_address)

BaseWSGIServerserve_forever

    def serve_forever(self, poll_interval: float = 0.5) -> None:
        self.shutdown_signal = False
        try:
            # 调用父类的serve_forever,即BaseServer.serve_forever
            super().serve_forever(poll_interval=poll_interval)
        except KeyboardInterrupt:
            pass
        finally:
            self.server_close()

BaseServer.serve_forever

    def serve_forever(self, poll_interval=0.5):
        self.__is_shut_down.clear()
        try:
            with _ServerSelector() as selector:
                selector.register(self, selectors.EVENT_READ)

                while not self.__shutdown_request:
                    ready = selector.select(poll_interval)
                    # bpo-35017: shutdown() called during select(), exit immediately.
                    if self.__shutdown_request:
                        break
                    if ready:
                        self._handle_request_noblock() # 这一步是工作语句。跟踪

                    self.service_actions()
        finally:
            self.__shutdown_request = False
            self.__is_shut_down.set()

BaseServer._handle_request_noblock

class BaseServer: 
    
    ...
    def __init__(self, server_address, RequestHandlerClass):
        self.server_address = server_address
        self.RequestHandlerClass = RequestHandlerClass
        self.__is_shut_down = threading.Event()
        self.__shutdown_request = False
    ...
    
    def _handle_request_noblock(self):
        try:
            request, client_address = self.get_request()
        except OSError:
            return
        if self.verify_request(request, client_address):
            try:
                self.process_request(request, client_address)  # 处理request
            except Exception:
                self.handle_error(request, client_address)
                self.shutdown_request(request) # 关闭request
            except:
                self.shutdown_request(request)
                raise
        else:
            self.shutdown_request(request)
            
    def process_request(self, request, client_address):
        self.finish_request(request, client_address) # 调用finish_request
        self.shutdown_request(request)
        
    def finish_request(self, request, client_address):
        # 最重要的一步。
        # 这里的RequestHandlerClass在Flask中默认是WSGIRequestHandler
        # 传递的值分别是request请求, client_address地址和self(即BaseWSGIServer实例)
        self.RequestHandlerClass(request, client_address, self) 

    def shutdown_request(self, request):
        self.close_request(request)

WSGIRequestHandler

WSGIRequestHandler没有__init__函数,跟踪父类**BaseRequestHandler**

# 根据名字知道这是一个基类。
class BaseRequestHandler:

    def __init__(self, request, client_address, server):
        self.request = request
        self.client_address = client_address
        self.server = server # 
        self.setup()
        try:
            # 最重要的一步,调用了WSGIRequestHandler.handle函数。
            self.handle() 
        finally:
            self.finish()

    def setup(self):
        pass

    def handle(self):
        pass

    def finish(self):
        pass

werkzeug包中,WSGIRequestHandler继承了BaseRequestHandler,也就是调用WSGIRequestHandler.handle()

WSGIRequestHandler.handle()

    def handle(self) -> None:
        """Handles a request ignoring dropped connections."""
        try:
            # 这里的self是WSGIRequestHandler实例,跟进
            BaseHTTPRequestHandler.handle(self) 
        except (ConnectionError, socket.timeout) as e:
            self.connection_dropped(e)
        except Exception as e:
            if self.server.ssl_context is not None and is_ssl_error(e):
                self.log_error("SSL error occurred: %s", e)
            else:
                raise
        if self.server.shutdown_signal:
            self.initiate_shutdown()

BaseHTTPRequestHandler.handle(self)

    def handle(self):
        # 这里的self是WSGIRequestHandler实例
        """Handle multiple requests if necessary."""
        self.close_connection = True

        self.handle_one_request()# 处理一个request,跟进该函数
        while not self.close_connection:
            self.handle_one_request()

WSGIRequestHandler.handle_one_request()

    def handle_one_request(self) -> None:
        """Handle a single HTTP request."""
        self.raw_requestline = self.rfile.readline()
        if not self.raw_requestline:
            self.close_connection = True
        elif self.parse_request():
            self.run_wsgi() # 终于到了run_wsgi

run_wsgi

    def run_wsgi(self) -> None:
        if self.headers.get("Expect", "").lower().strip() == "100-continue":
            self.wfile.write(b"HTTP/1.1 100 Continue\r\n\r\n")

        self.environ = environ = self.make_environ()
        status_set: t.Optional[str] = None
        headers_set: t.Optional[t.List[t.Tuple[str, str]]] = None
        status_sent: t.Optional[str] = None
        headers_sent: t.Optional[t.List[t.Tuple[str, str]]] = None

        def write(data: bytes) -> None:
            ...# 往socket中写入response
            self.wfile.write(data)
            self.wfile.flush()

        def start_response(status, headers, exc_info=None):  # type: ignore
            nonlocal status_set, headers_set
            if exc_info:
                try:
                    if headers_sent:
                        raise exc_info[1].with_traceback(exc_info[2])
                finally:
                    exc_info = None
            elif headers_set:
                raise AssertionError("Headers already set")
            status_set = status
            headers_set = headers
            return write

        def execute(app: "WSGIApplication") -> None:
            # 调用Flask.__call__(self, environ, start_response)
            application_iter = app(environ, start_response)
            try:
                for data in application_iter:
                    write(data)
                if not headers_sent:
                    write(b"")
            finally:
                if hasattr(application_iter, "close"):
                    application_iter.close()  # type: ignore

        try:
            execute(self.server.app) # self.server.app就是Flask的实例
        except (ConnectionError, socket.timeout) as e:
            self.connection_dropped(e, environ)
        except ...
        ...

总结

总的来说就是通过使用werkzeug来代理一个Server,使用WSGIRequestHandler调用到Flask.__call__函数,然后获取返回值,再通过socket返回到客户端。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值