1. 中间件的概念
在 FastAPI 里,中间件(Middleware)是一个 在每次请求到达路由处理函数之前 和 响应返回给客户端之前 执行的函数。
它相当于一个“拦截器”或“过滤器”,可以用来:
-
在请求进入时做一些预处理(如日志、鉴权、限流等)
-
在响应返回时做一些加工(如数据加密、统一格式化、添加响应头等)
简单理解:
客户端 → (请求预处理) → 路由函数 → (响应后处理) → 客户端
2. 工作原理
FastAPI 的中间件基于 Starlette,它是 ASGI(异步服务器网关接口)的一个实现。
中间件会包裹你的应用,形成一个“洋葱模型”:
请求进入
↓
中间件A(请求处理部分)
↓
中间件B(请求处理部分)
↓
路由处理函数(业务逻辑)
↓
中间件B(响应处理部分)
↓
中间件A(响应处理部分)
↓
响应返回
3. 中间件的编写方式
3.1 使用 @app.middleware 装饰器
最常见方式,直接注册一个异步函数:
from fastapi import FastAPI, Request
import time
app = FastAPI()
@app.middleware("http") # 声明这是一个 HTTP 中间件
async def log_requests(request: Request, call_next):
start_time = time.time()
# 请求前处理
print(f"请求路径: {request.url.path}")
response = await call_next(request) # 继续执行下一个中间件或路由处理函数
# 响应后处理
duration = time.time() - start_time
print(f"处理时间: {duration:.4f}秒")
response.headers["X-Process-Time"] = str(duration)
return response
说明:
-
request:FastAPI 的请求对象 -
call_next:调用下一个中间件或实际的路由处理函数 -
必须返回
response
3.2 使用类继承 BaseHTTPMiddleware
当中间件逻辑复杂时,更推荐这种方式,因为它支持更灵活的初始化。
from fastapi import FastAPI, Request
from starlette.middleware.base import BaseHTTPMiddleware
app = FastAPI()
class CustomHeaderMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
# 请求前
print("进入中间件:添加自定义响应头")
response = await call_next(request)
# 响应后
response.headers["X-Custom-Header"] = "Hello Middleware"
return response
# 添加中间件
app.add_middleware(CustomHeaderMiddleware)
4. 常见中间件功能场景
| 场景 | 描述 | 示例 |
|---|---|---|
| 日志记录 | 记录请求的路径、方法、耗时等 | print(f"{request.method} {request.url.path}") |
| 统一响应格式 | 把所有返回数据包装成统一 JSON 格式 | {"code": 0, "data": ..., "msg": "success"} |
| 跨域处理 | CORS(跨域资源共享) | from fastapi.middleware.cors import CORSMiddleware |
| 请求限流 | 限制访问频率,防止接口被刷 | 用 Redis 存储 IP 访问次数 |
| 权限校验 | 在进入路由前验证 Token | 解析 JWT 令牌 |
| 响应压缩 | 压缩数据传输量(GZip、Brotli) | from fastapi.middleware.gzip import GZipMiddleware |
| 安全过滤 | 过滤 XSS、SQL 注入等特殊字符 | 正则替换或白名单过滤 |
5. FastAPI 内置常用中间件
FastAPI/Starlette 已经自带一些常用中间件,可以直接 app.add_middleware 使用:
5.1 跨域中间件
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 允许的源
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
5.2 GZip 压缩中间件
from fastapi.middleware.gzip import GZipMiddleware
app.add_middleware(GZipMiddleware, minimum_size=1000) # 超过 1000 字节才压缩
6. 中间件 vs 依赖(Dependencies)
| 对比项 | 中间件 | 依赖(Depends) |
|---|---|---|
| 作用范围 | 全局(所有路由) | 可作用于单个路由或全局 |
| 执行顺序 | 在路由处理函数前后 | 路由执行前(依赖结束就结束) |
| 适用场景 | 日志、跨域、统一响应 | 参数校验、权限控制、业务逻辑复用 |
✅ 总结
-
中间件是全局拦截器,请求和响应都会经过它
-
简单逻辑用
@app.middleware,复杂逻辑用BaseHTTPMiddleware -
常用场景包括日志、跨域、统一响应、限流、权限等
-
内置中间件(CORS、GZip)可以直接用,复杂需求可自定义
9864

被折叠的 条评论
为什么被折叠?



