Flask框架 之 session请求流程及源码解析

Falsk框架session请求流程

from flask import Flask

# 1. 实例化Flask对象
app = Flask(__name__)

# 2. 设置路由
"""
app.url_map = [
    ('/index',index),
    ('/login',login),
]
"""
@app.route('/index')
def index():
    return "index"

if __name__ == '__main__':
    # 3. 启动socket服务端
    app.run()

    # 4. 用户请求到来
    app.__call__
    app.wsgi_app
    app.request_class
    app.session_interface

请求到来

当请求到来,执行__call__方法。看一下源码。

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."""
    #environ:  请求相关的所有数据(wsgi做了初步封装)
    #start_response:用于设置响应相关的所有数据。
    return self.wsgi_app(environ, start_response)

 environ: 请求相关的所有数据,wsgi将原生的请求做第一步处理,把字符串分割。(wsgi做了初步封装)

start_response:用于设置响应相关的所有数据。

我们看到了一个新的函数。wsgi_app().点进去看一下。

def wsgi_app(self, environ, start_response):
        '''
        1、获取environ并对其进行再次封装。就成了我们要的request.
 
        2、从environ获取名称为session的cookie值,解密,反序列化成字典
 
        3、两个东西放到“某个神奇”的地方。
        '''
      ctx = self.request_context(environ)
      error = None
      try:
          try:
             ctx.push()
              # 4、执行视图函数
              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
                '''
              5、“某个神奇”的地方获取session,加密,序列化,写入cookie
              6、“某个神奇”的地方位置清空 (请求结束)
                '''
          ctx.auto_pop(error)

小总结:  

1、获取environ并对其进行再次封装。就成了我们要的request.

2、从environ获取名称为session的cookie值,解密,反序列化成字典

3、两个东西放到“神奇”的地方。

4、执行视图函数

5、“某个神奇”的地方获取session,加密,序列化,写入cookie
6、“某个神奇”的地方位置清空

  

request_context是什么?点进去看一下。

说明了一个问题:

RequestContext把我们的对象和请求封装到了一个类。我们对这个类进行实例化,看一下做了什么事?

我们没传request,但是传了environ.

如果request_class是一个类,那就是又进行了一次实例化。实例化之后得到一个对象request。

request = app.request_class(environ)是不是对请求在做封装,那request_class是啥?我们来看一下。发现点不进去。

在py文件写一句app.request_class,点进去。

是一个request的类。

 回到wsgi_app类中,我们会得到:ctx.request=Request(environ)。

environ是一个原始的请求对象,但是现在被Request包裹,就不是原始的了。我们就可以执行".args",".form",".method"等。会自动帮我们去原始的数据解析。

通过以上,我们还可以得到一句ctx.session=None.

现在ctx已经封装了两个值了,一个是请求相关的数据,一个是session,把它放到“某个神奇的地方”。

视图函数:

下面我们来看视图函数:

在ctx.push()中点进去,上面的看不懂就不管了。

我们第一次请求session为空。进入if条件语句。app全局的。看一下session_interface.

在py文件中写一句:app.session_interface

是一个对象,就相当于对象执行了open_session方法,返回给self.session,就相当于给之前的session重新赋值。

那这个open_session是干啥的呢?

def open_session(self, app, request):
    s = self.get_signing_serializer(app)  #加密
    if s is None:
        return None
    val = request.cookies.get(app.session_cookie_name)  #去cookie中取值
    if not val:  #第一次访问为空执行
        return self.session_class()  #返回{}
    max_age = total_seconds(app.permanent_session_lifetime)
    try:
        data = s.loads(val, max_age=max_age) #loads:并反序列化 val:原来的值
        return self.session_class(data) #{"k1":123}
    except BadSignature:
        return self.session_class()

open_session返回啥self.session中就是啥。

现在回到我们的wsgi_app类中,

#将ctx放到“某个神奇的地方”
#执行SecureCookieSessionInterface.open_session(),去cookie中获取值,并给ctx.session重新赋值。  

现在才开始真正走视图函数 

进入full_diapatch_request.

红框继续进入:

 

善后工作如何执行,继续进入:

看一下save_session:

前面的不用看,就看一下咱们用得到的。

就是完成了这一步:

其实是这样的。

最后执行

这大概就是Flask框架中sesion的请求流程。说了这么多,其实真正实现咱们想要的功能的就是两个方法:open_session,save_session.请求进来执行open_session,请求走的时候执行save_session。

默认都是调用app.session_interface。

总结

流程:
    请求到来:
- 请求到来之后wsgi会触发__call__方法,由__call__方法再次调用wsgi_app方法,
            将请求和session相关封装到ctx = RequestContext对象中。
            将app和g封装到app_ctx = AppContext对象中。
            再通过LocalStack对象将ctx、app_ctx封装到Local对象中。
                                
    获取数据:
            通过LocalProxy对象+偏函数,调用LocalStack去Local中获取响应ctx、app_ctx中封装的值。
                    
      
    请求结束:
            调用LocalStack的pop方法,将ctx和app_ctx移除。

 

posted @ 2018-06-26 15:13  高~雅  阅读(357)  评论(0编辑  收藏  举报