90%的场景用@app.before_request就够了,它轻量、易调试、与flask生命周期对齐;仅当需拦截原始wsgi环境(如修改environ、提前返回响应或协议适配)时才用app.wsgi_app,否则易导致上下文未初始化等错误。

中间件函数必须用 @app.before_request 还是 app.wsgi_app?
直接说结论:90% 的场景用 @app.before_request 就够了,它轻量、易调试、与 Flask 生命周期对齐;只有需要拦截原始 WSGI 环境(比如改 environ、提前返回响应、或做底层协议适配)时,才该动 app.wsgi_app。后者容易绕过 Flask 的错误处理和上下文栈,一不小心就让 g 或 request 变成未初始化状态。
常见错误现象:RuntimeError: Working outside of application context —— 这往往是因为在 app.wsgi_app 里调用了 current_app 或 request,而此时 Flask 上下文还没 push。
-
@app.before_request在每次请求进入路由前执行,能安全访问request、g、session -
app.wsgi_app是 WSGI callable 的入口,适合做日志埋点、协议转换、静态文件短路,但别在里面调用 Flask 内部对象 - 若需全局异常捕获,优先用
@app.errorhandler配合before_request,而不是在 WSGI 层 try-except
如何避免中间件拖慢所有请求?
性能瓶颈通常不出现在逻辑本身,而出现在「同步阻塞」和「重复计算」上。比如在 @app.before_request 里调用一次远程鉴权 API,会让每个请求多等 200ms;又或者每次解析同一段 JWT header,却没缓存 decoded 结果。
- 鉴权、限流、日志等中间件,优先用本地缓存(如
functools.lru_cache)或 Redis 缓存结果,别每次 decode 同一个 token - 耗时操作(如调用外部 HTTP 接口、读大文件)必须异步化——但注意:Flask 默认不支持 async
before_request,得用asyncio.run()包裹(仅限低并发),或迁移到Quart - 用
request.path.startswith('/static/')提前 return,跳过非业务路径的中间件逻辑
before_request 和 after_request 怎么配合做请求追踪?
单靠 before_request 记 start time 不够,必须和 after_request 配合才能算出真实耗时;而且要注意:如果视图函数抛异常,after_request 不会触发,得靠 teardown_request 补位。
- 在
before_request中写:g.start_time = time.time() - 在
after_request中加 header:response.headers['X-Response-Time'] = f'{time.time() - g.start_time:.3f}s' - 但若视图抛出未被捕获的异常,
after_request不执行,所以还得加@app.teardown_request做兜底日志记录 - 别在
after_request里修改response.data(比如加水印),这会触发完整 body 加载,吃内存;改response.headers是安全的
为什么中间件里不能直接改 request.json?
因为 request.json 是只读属性,底层调用的是 get_json(cache=True),多次访问返回同一对象;直接赋值会报 AttributeError,而试图替换整个 request.json 会导致后续调用失效。
- 想预处理 JSON 数据,应该在
before_request里手动解析:data = request.get_json(force=True),然后存到g.parsed_json = data - 若需修改原始请求体(比如脱敏字段),得在 WSGI 层操作
environ['wsgi.input'],但代价高,且破坏 Flask 的 request 缓存机制 - 更稳妥的做法:定义装饰器封装视图函数,在函数内部做数据清洗,而非在中间件层强行 mutate 请求对象
真正难的不是写中间件,而是判断哪部分逻辑「必须」在中间件里做,哪部分其实该下沉到 service 层或上提到网关。多数性能问题,根源不在中间件写得不够炫,而在边界没划清。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











