Flask框架(五) —— session源码分析

session源码分析

1、请求来了,执行__call__方法

# 请求来了执行 __call__方法
if __name__ == '__main__':
app.__call__
app.run()

2、__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."""
return self.wsgi_app(environ, start_response)

3、调用__call__方法

    def wsgi_app(self, environ, start_response):
# 1.得到request,和空的session
# ctx是RequestContext的对象,对象里面有空的session和request
ctx = self.request_context(environ)
error = None
try:
try:
# 2.从request中的cookie中取出value,解密过转成session对象 --> open_session
ctx.push()
# 3.路由映射到函数,执行函数,然后保存session --> save_session,请求结束
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)

3.1、ctx = self.request_context(environ) --- 得到空的session

    # 1. 获得RequestContext对象 ---> ctx
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) # request_class = Request
self.request = request
self.url_adapter = app.create_url_adapter(self.request)
self.flashes = None
self.session = None

3.2、ctx.push() --- 调用open_session方法

    # 2.ctx.push() --- 调用open_session方法
def push(self):
"""Binds the request context to the current context."""
top = _request_ctx_stack.top
if top is not None and top.preserved:
top.pop(top._preserved_exc) # Before we push the request context we have to ensure that there
# is an application context.
app_ctx = _app_ctx_stack.top
if app_ctx is None or app_ctx.app != self.app:
app_ctx = self.app.app_context()
app_ctx.push()
self._implicit_app_ctx_stack.append(app_ctx)
else:
self._implicit_app_ctx_stack.append(None) if hasattr(sys, 'exc_clear'):
sys.exc_clear() _request_ctx_stack.push(self) # Open the session at the moment that the request context is available.
# This allows a custom open_session method to use the request context.
# Only open a new session if this is the first time the request was
# pushed, otherwise stream_with_context loses the session. # 从request中的cookie中取出value,(有解密过程)转成session对象
# 正常情况下此时session中有值了
# 如果request中没有cookie,那么session中仍然没有值
if self.session is None:
# session_interface = SecureCookieSessionInterface()
session_interface = self.app.session_interface
# 2.1 opensession(),SecureCookieSessionInterface类中
self.session = session_interface.open_session(
self.app, self.request
) if self.session is None:
self.session = session_interface.make_null_session(self.app)

3.2.1、session_interface.open_session() --- 从通过session的名字取出cookie的值转成session

# 2.1.session_interface.open_session()
class SecureCookieSessionInterface(SessionInterface):
def open_session(self, app, request):
s = self.get_signing_serializer(app)
if s is None:
return None
# 通过session的名字取出cookie的值,key:value形式,得到的是json格式的字符串
val = request.cookies.get(app.session_cookie_name)
if not val:
return self.session_class()
max_age = total_seconds(app.permanent_session_lifetime)
try:
# 将json格式字符串转成字典
data = s.loads(val, max_age=max_age)
# 返回一个特殊的字典
return self.session_class(data)
except BadSignature:
return self.session_class()

3.3、self.full_dispatch_request() --- 路由分发,执行函数,写入session

# 3.self.full_dispatch_request()
1 执行before_request
2 执行视图函数
3 把session写入
if not self.session_interface.is_null_session(ctx.session):
self.session_interface.save_session(self, ctx.session, response) def full_dispatch_request(self):
self.try_trigger_before_first_request_functions()
try:
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)
# 3.1 把session保存写入cookie
return self.finalize_request(rv)

3.3.1、self.finalize_request(rv) --- 调用save_session()保存写入session

# 3.1.self.finalize_request(rv)
def finalize_request(self, rv, from_error_handler=False):
response = self.make_response(rv)
try:
# 利用save_session 保存写入session
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
3.3.1.1、self.process_response(response) --- 调用save_session方法
# 保存写入session
def process_response(self, response):
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):
# 调用save_session方法保存写入session
self.session_interface.save_session(self, ctx.session, response)
return response
save_session()方法
class SecureCookieSessionInterface(SessionInterface):
def save_session(self, app, session, response):
domain = self.get_cookie_domain(app)
path = self.get_cookie_path(app) # If the session is modified to be empty, remove the cookie.
# If the session is empty, return without setting the cookie.
if not session:
if session.modified:
response.delete_cookie(
app.session_cookie_name,
domain=domain,
path=path
) return # Add a "Vary: Cookie" header if the session was accessed at all.
if session.accessed:
response.vary.add('Cookie') if not self.should_set_cookie(app, session):
return httponly = self.get_cookie_httponly(app)
secure = self.get_cookie_secure(app)
samesite = self.get_cookie_samesite(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,
expires=expires,
httponly=httponly,
domain=domain,
path=path,
secure=secure,
samesite=samesite
)
博客内容仅供参考,部分参考他人优秀博文,仅供学习使用

Flask框架(五) —— session源码分析的更多相关文章

  1. Flask框架(三)—— 请求扩展、中间件、蓝图、session源码分析

    Flask框架(三)—— 请求扩展.中间件.蓝图.session源码分析 目录 请求扩展.中间件.蓝图.session源码分析 一.请求扩展 1.before_request 2.after_requ ...

  2. DotNetty网络通信框架学习之源码分析

    DotNetty网络通信框架学习之源码分析 有关DotNetty框架,网上的详细资料不是很多,有不多的几个博友做了简单的介绍,也没有做深入的探究,我也根据源码中提供的demo做一下记录,方便后期查阅. ...

  3. 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)

    1 智能生活项目需求 看一个具体的需求 1) 我们买了一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作. 2) 这些智能家电来自不同的厂家,我们不想针 ...

  4. $Django cbv源码分析 djangorestframework框架之APIView源码分析

    1 CBV的源码分析 #视图 class login (View): pass #路由 url(r'^books/$', views.login.as_view()) #阅读源码: #左侧工程栏--- ...

  5. 深入理解分布式调度框架TBSchedule及源码分析

    简介 由于最近工作比较忙,前前后后花了两个月的时间把TBSchedule的源码翻了个底朝天.关于TBSchedule的使用,网上也有很多参考资料,这里不做过多的阐述.本文着重介绍TBSchedule的 ...

  6. Django——Session源码分析

    首先我们导入django.contrib.sessions.middleware这个中间件,查看里面的Session源码 from django.contrib.sessions.middleware ...

  7. 设计模式(二十一)——解释器模式(Spring 框架中SpelExpressionParser源码分析)

    1 四则运算问题 通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 1) 先输入表达式的形式,比如 a+b+c-d+e,  要求表达式的字母不能重复 2) 在分别输入 a ,b, c, ...

  8. Nginx学习笔记(五) 源码分析&内存模块&内存对齐

    Nginx源码分析&内存模块 今天总结了下C语言的内存分配问题,那么就看看Nginx的内存分配相关模型的具体实现.还有内存对齐的内容~~不懂的可以看看~~ src/os/unix/Ngx_al ...

  9. ⑤NuPlayer播放框架之GenericSource源码分析

    [时间:2017-01] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,GenericSource] 0 导读 GenericSource是NuPlayer:: ...

随机推荐

  1. java集合源码分析几篇文章

    java集合源码解析https://blog.csdn.net/ns_code/article/category/2362915

  2. puppet运维自动化之用户管理

    系统管理员离不开账户管理,账户管理,密码管理,开发机器,测试机器,线上机器,都需要创建用户,并给与相关用户的权限.你如果要创建100个,1000个账户和密码,你会不会疯掉,如何在1分钟完成百上千个账户 ...

  3. urllib详细版

    urllib是python内置的处理HTTP请求的库,主要包含以下四个模块 request 模块,是最基本的处理HTTP请求的模块. error 异常处理模块,如果出现请求错误,可以捕获这些错误,保证 ...

  4. 磁盘IO过高时的参考

    主要命令:echo deadline > /sys/block/sda/queue/scheduler 注:以下的内容仅是提供参考,如果磁盘IO确实比较大的话,是数据库,可以进行读写分离或者分库 ...

  5. JAVA笔记18-容器之二增强的for循环(不重要)

    JDK1.5增强的for循环(foreach??)

  6. Codeforces 919E Congruence Equation ( 数论 && 费马小定理 )

    题意 : 给出数 x (1 ≤ x ≤ 10^12 ),要求求出所有满足 1 ≤ n ≤ x 的 n 有多少个是满足 n*a^n  = b ( mod p ) 分析 : 首先 x 的范围太大了,所以使 ...

  7. Python黑科技:在家远程遥控公司电脑,python+微信一键连接!

    有时候需要远程家里的台式机使用,因为我平时都是用 MAC 多,但是远程唤醒只能针对局域网,比较麻烦,于是我想用微信实现远程唤醒机器. 准备工作 本程序主要是实现远程管理 Windows10操作系统的开 ...

  8. opengl中相关的计算机图形变换矩阵之:齐次坐标 (摘编)

    模型视图变换(几何变换)矩阵: 1. 齐次坐标:两条平行线也可以相交. 在欧几里得空间中,两条平行线是无法相交的,但是在投影空间(Projective Space)这条定理就不再适用了. 比如上图中, ...

  9. Shell 变量/echo命令

    Shell 教程 Shell 是一个用C语言编写的程序,它是用户使用Linux的桥梁.Shell既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程序提供了一个界面,用户 ...

  10. Maven开发环境搭建

    配置Maven流程: 1.下载Maven,官网:http://maven.apache.org/ 2.安装到本地: 1 ).解压apache-maven-x.x.x-bin.zip文件 2 ).配置M ...