全书目录

第二十九篇:Flask 完全指南 —— 轻骑兵微服务街区宇宙

第十一章:请求生命周期 —— 一位信使穿过轻骑兵街区时发生了什么

1 分钟 132 字 第 528 / 962 个阅读单元

这张图非常关键,吃透它,Flask 的很多“玄学问题”都会变简单。

text
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
   │
   ▼
响应返回客户端

几个最常见的钩子长这样:

py
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_requestteardown_appcontext 就算发生异常也会跑。 所以收尾函数应该写成“尽量稳、少假设、只清理”的风格。