1. 程式人生 > >flask--session源碼解析

flask--session源碼解析

__name__ closed ssi ons byte stc contex is_null nali

一: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源碼解析