flask--session源码解析

Posted forjie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了flask--session源码解析相关的知识,希望对你有一定的参考价值。

 

一:session源码开始

1,创建起始连接

from flask import Flask
from index import app

app=Flask(__name__)


if __name__ == __main__:
    app.__call__
    app.run()

2,开始请求app.__call__

    def __call__(self, environ, start_response):
        """Shortcut for :attr:`wsgi_app`."""
        return self.wsgi_app(environ, start_response)

 

3,执行wsgi_app方法

技术分享图片
def wsgi_app(self, environ, start_response):
    ctx = self.request_context(environ)
        ctx.push()
        error = None
        try:
            try:
                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)
def wsgi_app(self, environ, start_response):

 


==> ctx = self.request_context(environ)
技术分享图片
def request_context(self, environ):
    return RequestContext(self, environ)

class RequestContext(object):
    def __init__(self, app, environ, request=None):
           self.app = app
           if request is None:
            request = app.request_class(environ)
           self.request = request
生成RequestContext()对象 封装请求相关的数据(request,session)

 

==>  ctx.push()
def push(self):
    self.session = self.app.open_session(self.request) #开始运行session
        if self.session is None:        #如果没有session
            self.session = self.app.make_null_session()

 

==> def open_session(self, app, request)
开始执行session
技术分享图片
    def open_session(self, app, request):
        sid = request.cookies.get(app.session_cookie_name)  #如果能从cookie拿到session的话
        if not sid:
            sid = self._generate_sid()
            return self.session_class(sid=sid, permanent=self.permanent)    #如果没有session,则返回一个空字典
        if self.use_signer:
            signer = self._get_signer(app)
            if signer is None:
                return None
            try:
                sid_as_bytes = signer.unsign(sid)
                sid = sid_as_bytes.decode()
            except BadSignature:
                sid = self._generate_sid()
                return self.session_class(sid=sid, permanent=self.permanent)

        if not PY2 and not isinstance(sid, text_type):
            sid = sid.decode(utf-8, strict)
        val = self.redis.get(self.key_prefix + sid)
        if val is not None:
            try:
                data = self.serializer.loads(val)    #加密val
                return self.session_class(data, sid=sid) 
            except:
                return self.session_class(sid=sid, permanent=self.permanent)
        return self.session_class(sid=sid, permanent=self.permanent)  #把session加到字典里
View Code

 

==>  def full_dispatch_request(self):
当视图函数执行完成,要把session保存到session里面
技术分享图片
self.try_trigger_before_first_request_functions()
        try:
            #视图函数开始,发送信号
            print(self)
            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)
View Code

 

 

 

==> def finalize_request(self, rv, from_error_handler=False):
上面是视图函数全部执行完成,开始保存数据,以及session,在process_responce里面存有所有数据
技术分享图片
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
View Code

 

==> def process_response(self, response):
这里处理保存session,调用
save_session
技术分享图片
ctx = _request_ctx_stack.top
        bp = ctx.request.blueprint
        funcs = ctx._after_request_functions
        if bp is not None and bp in self.after_request_funcs:
            funcs = chain(funcs, reversed(self.after_request_funcs[bp]))
        if None in self.after_request_funcs:
            funcs = chain(funcs, reversed(self.after_request_funcs[None]))
        for handler in funcs:
            response = handler(response)
        if not self.session_interface.is_null_session(ctx.session):
            self.save_session(ctx.session, response)
        return response
View Code

 

==> def save_session(self, app, session, response):
def save_session(self, app, session, response):
    domain = self.get_cookie_domain(app)   #域名
        path = self.get_cookie_path(app)    #路径
            if not session:
            if session.modified:
                response.delete_cookie(app.session_cookie_name,
                                       domain=domain, path=path)
            return
            if not self.should_set_cookie(app, session):
            return

        httponly = self.get_cookie_httponly(app)
        secure = self.get_cookie_secure(app)
        expires = self.get_expiration_time(app, session)
        val = self.get_signing_serializer(app).dumps(dict(session))  加密
        response.set_cookie(app.session_cookie_name, val,           #最后保存到cookie里面
                            expires=expires, httponly=httponly,
                            domain=domain, path=path, secure=secure)

 





 










以上是关于flask--session源码解析的主要内容,如果未能解决你的问题,请参考以下文章

Flask - Session

关于Flask session实现的一些疑惑与思考

flask——session

flask session

六十一:Flask.Session之flask操作session

Flask初识