这张图非常关键,吃透它,Flask 的很多“玄学问题”都会变简单。
HTTP 请求
│
▼
WSGI Server 调用 Flask app
│
▼
创建 RequestContext
创建 AppContext
│
▼
current_app / g 可用
request / session 可用
│
▼
匹配 URL 规则
│
▼
before_request
│
├── 若直接 return,提前结束
└── 否则继续
▼
view function / MethodView
│
├── 可能抛异常
├── 可能返回 str / dict / tuple / Response
└── 可能调用 render_template / jsonify
▼
errorhandler(如有异常)
│
▼
转换为 Response
│
▼
after_request
│
▼
保存 session
│
▼
teardown_request
teardown_appcontext
│
▼
响应返回客户端几个最常见的钩子长这样:
import time
import uuid
from flask import Flask, g, request, jsonify
app = Flask(__name__)
@app.before_request
def mark_request():
g.request_id = str(uuid.uuid4())
g.started_at = time.perf_counter()
@app.after_request
def add_headers(response):
duration = time.perf_counter() - g.started_at
response.headers["X-Request-Id"] = g.request_id
response.headers["X-Elapsed"] = f"{duration:.6f}"
return response
@app.teardown_request
def teardown_request(exc):
# 这里做收尾,不要依赖“前面一定全部成功执行过”
pass
@app.errorhandler(404)
def not_found(e):
return jsonify(error="mission not found"), 404要特别记一句:
teardown_request 和 teardown_appcontext 就算发生异常也会跑。
所以收尾函数应该写成“尽量稳、少假设、只清理”的风格。