全局对象request解析

由源代码布局可知,globals.py保存flask的全局对象,包括 1. current_app 2. request 3. g

我们首先来讲讲request对象: 源码:

from functools import partial
from werkzeug.local import LocalProxy
from werkzeug.local import LocalStack

def _lookup_req_object(name):
    top = _request_ctx_stack.top
    if top is None:
        raise RuntimeError(_request_ctx_err_msg)
    return getattr(top, name)

_request_ctx_stack = LocalStack()
request = LocalProxy(partial(_lookup_req_object, "request"))

由代码可知,request的实现主要依赖于LocalProxyLocalStack,简单说一说LocalProxyLocalStack

  • LocalProxy:werkzeug实现的一种代理对象,可知实现被代理对象的动态更新。

  • LocalStack:LocalStack是werkzeug库实现的栈,对象压入的规则简单总结为先入后出,并且可以方便的访问栈顶对象以及各种常用操作,比如push、pop等。

werkzeug实现的具体细节,感兴趣的同学可以翻看源码,后续我们也会一起来看。

接下来,看一下request的对象的具体的工作原理和生命周期:

  • 生命周期:request的对象的进栈和出栈的逻辑都在Flask类的wsgi_app方法中进行的,我们来看一下:

由代码可知,当http请求到达时,flask先通过environ参数构造RequestContext对象ctx,然后调用ctx.push(),在请求处理完毕后调用ctx.auto_pop(error),整个请求流程就结束了,request的进栈和出栈也同时完成。

接下来看看RequestContextpush方法,到底做了什么操作:

push方法可知,此时不仅进行reqeuest的入栈操作,同时进行app对象的入栈操作,这样我导入from flask import request,就可以保障_request_ctx_stack的栈顶是当前请求信息构造的request对象,方便我们对请求信息的读取,并在处理完毕后,进行pop操作,清理_request_ctx_stack,等待下次请求的到达。

  • 工作原理

由全局变量的逻辑可知,request本质是RequestContext实例的request属性,而RequestContext实例的request属性是Flask类的request_class属性,即Request类,综合而看request就是Request类实例化对象。而Request有多个父类,包含以下种类:

  • JSONMinxin

  • AcceptMixin

  • ETagRequestMixin

  • UserAgentMixin

  • AuthorizationMixin

  • CORSRequestMixin

  • CommonRequestDescriptorsMixin

这样request实例就被赋予多种属性与方法,方便在调用时访问当前http请求的各种信息。

Last updated

Was this helpful?