flask-源码-request

Flask-request

基本点

  • flask request请求周期基本分为三个点:
  1. 请求进入后存储request 与 session
  • 这个地方就是生成request请求对象和请求上下文环境,flask上下文概念包含两个方面,一个是请求上下文,另一个是应用上下文,这两个单独放在一章来阐述
  1. 遍历flask中间件(before_request),信号相关,路由分发获取结果
  2. 遍历flask中间件(after_request),封装response,并将资源移除释放
  • 以下我整理了部分过程,但是不够完善,日后做修改,如果有错误可以提出做修改
  • 增加时序图,基本流程是这样,需要看着代码自己深入了解
  • 重要的基本流程框架是**wsgi_app(self, environ, start_response)**它包含了整个请求过程,具体的内部细节需要大家到函数内部去看一下

基本流程图1

full_dispatch_request
LocalStack-class
globals-pyfile
RequestContext-class
app-obj
response
self.finalize_request
self.dispatch_request
self.preprocess_request
request_started.send
self.try_trigger_before_first_request_functions
self.full_dispatch_request
_request_ctx_stack
LocalStack
self._local.stack
_request_ctx_stack.push
ctx
RequestContext
ctx.push
self.request_context
self.wsgi_app
__call__

基本流程图2

app RequestContext _request_ctx_stack requset __call__ self.wsgi_app self.request_context 生成RequestContext obj ctx 返回ctx对象 ctx.push() 把ctx对象放在了flask的local对象里,通过id号区分 _request_ctx_stack.push(self) 将ctx传过来,ctx中有当前的request与session 存储requset与session到self._local.stack 生成self.session 路由分发执行函数返回response self.try_trigger_before_first_request_functions() self.request_started.send(self) self.self.preprocess_request() self.dispatch_request() self.self.finalize_request(rv) loop [self.full_dispatch_request()] response ctx.auto_pop(error) 将ctx对象从local中移除 app RequestContext _request_ctx_stack

class Flask(_PackageBoundObject):
    ## __call__
    def __call__(self, environ, start_response)
       return self.wsgi_app(environ, start_response)

    ## wsgi_app
    def wsgi_app(self, environ, start_response):
  
        ## 获取ctx对象,RequestContext对象
        ## 内部有当前请求的request 与 session
        ## 上下文相关
        ctx = self.request_context(environ)
        error = None
        try:
            try:
               # 把ctx对象放在了flask的local对象里,通过id号区分
               ctx.push()
               # 路由分发,执行视图函数,返回结果
               response = self.full_dispatch_request()
            except Exception as e:
               error = e
               response = self.handle_exception(e)
            except:  # noqa: B001
               error = sys.exc_info()[1]
               raise
            return response(environ, start_response)
            finally:
                if self.should_ignore_error(error):
                    error = None
                # 将ctx对象从local中移除
                ctx.auto_pop(error)

    def full_dispatch_request(self):
        # 执行before_first_request函数
        self.try_trigger_before_first_request_functions()
        try:
            # 信号相关
            request_started.send(self)
            # before_request
            rv = self.preprocess_request()
            if rv is None:
                # 路由分发
                rv = self.dispatch_request()
        except Exception as e:
            rv = self.handle_user_exception(e)

        # 包装response
        return self.finalize_request(rv)


    def preprocess_request(self):

        bp = _request_ctx_stack.top.request.blueprint

        funcs = self.url_value_preprocessors.get(None, ())
        if bp is not None and bp in self.url_value_preprocessors:
            funcs = chain(funcs, self.url_value_preprocessors[bp])
        for func in funcs:
            func(request.endpoint, request.view_args)
        # before_request 函数列表
        funcs = self.before_request_funcs.get(None, ())
        if bp is not None and bp in self.before_request_funcs:
            funcs = chain(funcs, self.before_request_funcs[bp])
        for func in funcs:
            rv = func()
            if rv is not None:
                return rv

    def dispatch_request(self):
        req = _request_ctx_stack.top.request
        if req.routing_exception is not None:
            self.raise_routing_exception(req)
        rule = req.url_rule
        if (
            getattr(rule, "provide_automatic_options", False)
            and req.method == "OPTIONS"
        ):
            return self.make_default_options_response()
        return self.view_functions[rule.endpoint](**req.view_args)

    def finalize_request(self, rv, from_error_handler=False):
        response = self.make_response(rv)
        try:
            response = self.process_response(response)
            request_finished.send(self, response=response)
        except Exception:
            if not from_error_handler:
                raise
            self.logger.exception(
                "Request finalizing failed with an error while handling an error"
            )
        return response

class LocalStack:
    def push(self, obj):
        """Pushes a new item to the stack"""
        # 将ctx传过来,ctx中有当前的request与session
        rv = getattr(self._local, "stack", None)
        if rv is None:
            # self._local是flask自己封装的local对象
            # 不同线程下放的值只有自己可用
            # 存储数据结构:{"线程id":{"stack"[ctx,]}}
            self._local.stack = rv = []
        rv.append(obj)
        return rv
## RequestContext
class RequestContext(object):
    def __init__(self, app, environ, request=None, session=None):
        self.app = app
        # 生成request对象,他为视图函数中使用的request对象
        if request is None:
            request = app.request_class(environ)
        self.request = request
        self.url_adapter = None
        try:
            self.url_adapter = app.create_url_adapter(self.request)
        except HTTPException as e:
            self.request.routing_exception = e
        self.flashes = None
        self.session = session
        self._implicit_app_ctx_stack = []
        self.preserved = False
        self._preserved_exc = None
        self._after_request_functions = []

    def push(self):
        top = _request_ctx_stack.top
        if top is not None and top.preserved:
            top.pop(top._preserved_exc)
        app_ctx = _app_ctx_stack.top
        if app_ctx is None or app_ctx.app != self.app:
            app_ctx = self.app.app_context()
            app_ctx.push()
            self._implicit_app_ctx_stack.append(app_ctx)
        else:
            self._implicit_app_ctx_stack.append(None)

        if hasattr(sys, "exc_clear"):
            sys.exc_clear()
       # self是ctx对象
       # _request_ctx_stack
        _request_ctx_stack.push(self)

        ## cookie取出转session
        if self.session is None:
            session_interface = self.app.session_interface
            self.session = session_interface.open_session(self.app, self.request)

            if self.session is None:
                self.session = session_interface.make_null_session(self.app)

        if self.url_adapter is not None:
            self.match_request()

猜你喜欢

转载自blog.csdn.net/DALAOS/article/details/113566518
今日推荐