一、 中间件的核心定义与洋葱模型
1. 什么是中间件?
中间件(Middleware)是一个在每次 HTTP 请求进入 FastAPI 应用时都会被自动执行的全局拦截函数。
它在请求到达具体路由函数之前 运行一次(前置拦截),并在路由函数执行完毕、响应返回给客户端之前再运行一次(后置处理)。
2. 洋葱模型(Onion Architecture)执行流
如果有多个中间件(如中间件 A 和中间件 B),执行顺序严格遵循"洋葱模型":
text
客户端请求 ➡️ [中间件 A 前置] ➡️ [中间件 B 前置] ➡️ 【路由处理函数】 ➡️ [中间件 B 后置] ➡️ [中间件 A 后置] ➡️ 客户端响应
- 请求阶段(由外向内):中间件 A 选执行,随后传递给中间件 B,最后到达路由函数。
- 响应阶段(由内向外):路由函数返回后,中间件 B 的后置代码先执行,最后由中间件 A 后置代码打包返回给客户端。
二、 中间件的五大典型应用场景
| 场景分类 | 核心功能 | 典型案例 |
|---|---|---|
| 1. 性能监控 | 统计每个 API 接口的执行耗时 | 在 Response Header 中注入 X-Process-Time |
| 2. 日志记录 | 全局打印/记录请求路径、IP 及响应状态码 | 记录所有 API 访问日志 |
| 3. 跨域处理 (CORS) | 允许前端不同域名/端口跨域访问 | 使用 FastAPI 内置的 CORSMiddleware |
| 4. 身份认证与拦截 | 拦截非法请求/校验 Token | 校验 Headers 中的 Authorization 凭证 |
| 5. 响应头/安全篡改 | 统一为所有响应添加安全防防御 Header | 注入 X-Frame-Options 或防盗链 Header |
三、 FastAPI 中间件代码实现语法
python
import time
from fastapi import FastAPI, Request
app = FastAPI()
# 使用 @app.middleware("http") 装饰器声明 HTTP 中间件
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
# --------------------------------------------------
# 1. 前置拦截处理(请求到达路由函数之前)
# --------------------------------------------------
start_time = time.time()
# --------------------------------------------------
# 2. 传递请求给后续的中间件或路由处理函数
# --------------------------------------------------
response = await call_next(request)
# --------------------------------------------------
# 3. 后置拦截处理(路由函数执行完毕,准备返回客户端之前)
# --------------------------------------------------
process_time = time.time() - start_time
# 统一在响应头中添加接口耗时 (单位:秒)
response.headers["X-Process-Time"] = str(process_time)
return response
关键参数解密
request: Request:包含客户端请求的所有信息(Header、IP、Path、Method 等)。call_next:一个异步回调函数。调用await call_next(request)意为"将请求交由下一个中间件或对应的视图函数去处理,并获取其返回的 response"。response:视图函数计算完毕后返回的 HTTP 响应对象。在return response之前可以对其 Header、Cookie 进行修改。
四、 内置官方中间件:CORS 跨域资源共享配置
1. 什么是跨域报错 (CORS Error)?
这是所有前后端分离项目都会遇到的第一个"死穴"。 出于安全考虑,浏览器天生带有**"同源策略"**机制。比如你的前端(Vue/React)跑在 http://localhost:8080,而去请求跑在 http://localhost:8000 的 FastAPI 后端接口时。因为它们的端口不一样(不同源),浏览器就会认为有安全风险,直接把请求拦截死,并在控制台报出一片红色的 CORS Error 报错。
2. 标准跨域放行配置
要解决这个问题,不用自己手写逻辑,FastAPI 官方已经内置了强大的 CORSMiddleware,只需要把它挂载到中间件洋葱模型的外层即可:
python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# 1. 设置允许访问的白名单源(前端的地址)
origins = [
"http://localhost:8080",
"http://localhost:3000",
"https://my-frontend-website.com"
]
# 2. 将 CORS 中间件加入洋葱模型
app.add_middleware(
CORSMiddleware,
allow_origins=origins, # 允许哪些前端地址跨域访问(如果写 ["*"] 则允许所有,但极不安全)
allow_credentials=True, # 是否允许前端携带 Cookie 等凭据
allow_methods=["*"], # 允许跨域请求的方法(GET, POST, PUT, DELETE等,"*"表示全放行)
allow_headers=["*"], # 允许跨域携带的请求头
)
【重点避坑】 :线上环境绝对禁止 把
allow_origins写成["*"]且同时开启allow_credentials=True,这不仅非常危险,而且很多浏览器会强制拒绝这种配置。务必老老实实配置具体的白名单域名!
五、 全局大串联 (终极总结)
1. 全链路协同思维链条
[收到请求] ➡️ [执行 CORS 等前置中间件拦截] ➡️ [抵达具体路由逻辑] ➡️ [执行中间件后置耗时统计] ➡️ [打上自定义 Header] ➡️ [响应出包给前端]
2. 【终极一句话速记】
"中间件像洋葱圈,一进一出跑两圈;跨域拦在最外层,配好白名单保平安。"