flask源码阅读笔记(1)-基本逻辑

一、前言

之前陆陆续续看过一点flask源码但不是很系统。最近计划把之前的笔记串起来,算是作为自己的积累。
为什么选择flask?答案比较简单:
- 代码量不是很大,核心部分也就万行左右
- 代码相对规范
- 注释很详细

flask 源码:https://github.com/pallets/flask

flask 文档:http://flask.pocoo.org/

falsk开发团队:https://www.palletsprojects.com

版本:1.1.dev

二、正文

1.wsgi的概念

全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。(其他语言不怎么提这个概念)

在flask框架中,wsgi负责连接server和我们APP里面的逻辑,完成整个HTTP请求的处理和响应。

2.编写一个demo app

    from flask import Flask

    app = Flask(__name__)

    @app.route('/')
    def hello():
        return 'Hello, World!'

启动我们的app后,即可访问到我们编写的逻辑(”Hello, World!”)了。当然一个HTTP请求是怎么到达我们函数,以及我们函数是怎么处理这块逻辑并将其返回,这个就是本文的重点。

3.request与response处理逻辑

  • app启动,Flask的call函数启动wsgi_app
    def __call__(self, environ, start_response):
        """The WSGI server calls the Flask application object as the
        WSGI application. This calls :meth:`wsgi_app` which can be
        wrapped to applying middleware."""
        return self.wsgi_app(environ, start_response)
  • 如图所示的,整个过程正常情况下涉及:wsgi_app、full_dispatch_request、preprocess_request、dispatch_request、finalize_request、make_response、process_response
    这里写图片描述

函数说明:

  • wsgi_app:生成request对象以及上下文环境。
   def wsgi_app(self, environ, start_response):
        """The actual WSGI application. This is not implemented in
        :meth:`__call__` so that middlewares can be applied without
        losing a reference to the app object. Instead of doing this::

            app = MyMiddleware(app)

        It's a better idea to do this instead::

            app.wsgi_app = MyMiddleware(app.wsgi_app)

        Then you still have the original application object around and
        can continue to call methods on it.

        .. versionchanged:: 0.7
            Teardown events for the request and app contexts are called
            even if an unhandled error occurs. Other events may not be
            called depending on when an error occurs during dispatch.
            # 省略部分注释
        """
        ctx = self.request_context(environ)
        error = None
        try:
            try:
                ctx.push()
                response = self.full_dispatch_request()
            except Exception as e:
                error = e
                response = self.handle_exception(e)
            except:
                error = sys.exc_info()[1]
                raise
            return response(environ, start_response)
        finally:
            if self.should_ignore_error(error):
                error = None
            ctx.auto_pop(error)
  • full_dispatch_request:主要用途:启动trigger,发送开始处理的signal,启动preprocess_request和finalize_request。
    def full_dispatch_request(self):
        """Dispatches the request and on top of that performs request
        pre and postprocessing as well as HTTP exception catching and
        error handling.

        .. versionadded:: 0.7
        """
        self.try_trigger_before_first_request_functions()
        try:
            request_started.send(self)
            rv = self.preprocess_request()
            if rv is None:
                rv = self.dispatch_request()
        except Exception as e:
            rv = self.handle_user_exception(e)
        return self.finalize_request(rv)
  • preprocess_request:主要call before_request_funcs
  • dispatch_request:开始调度request的处理,主要包括:匹配url规则、运行view_functions(用户自定义的函数)
    def dispatch_request(self):
        """Does the request dispatching.  Matches the URL and returns the
        return value of the view or error handler.  This does not have to
        be a response object.  In order to convert the return value to a
        proper response object, call :func:`make_response`.

        .. versionchanged:: 0.7
           This no longer does the exception handling, this code was
           moved to the new :meth:`full_dispatch_request`.
        """
        req = _request_ctx_stack.top.request
        if req.routing_exception is not None:
            self.raise_routing_exception(req)
        rule = req.url_rule
        # if we provide automatic options for this URL and the
        # request came with the OPTIONS method, reply automatically
        if getattr(rule, 'provide_automatic_options', False) \
           and req.method == 'OPTIONS':
            return self.make_default_options_response()
        # otherwise dispatch to the handler for that endpoint
        return self.view_functions[rule.endpoint](**req.view_args)
  • finalize_request: 主要是call make_response,然后发送结束request的signal
    官方注释:Given the return value from a view function this finalizes the request by converting it into a response and invoking the postprocessing functions. This is invoked for both normal request dispatching as well as error handlers.

  • make_response:将view_function的返回值转换为response_class
    最后通过response对象将结果返还给server。


参考文章:
https://blog.csdn.net/bestallen/article/details/54342120

猜你喜欢

转载自blog.csdn.net/u013128262/article/details/81057144