flask--session源碼解析
阿新 • • 發佈:2018-01-10
__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 responsedef wsgi_app(self, environ, start_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)
==> 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 responseView 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 responseView 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源碼解析