3.全局中间件_洋葱模型执行机制_跨域CORS配置

一、 中间件的核心定义与洋葱模型

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. 【终极一句话速记】

"中间件像洋葱圈,一进一出跑两圈;跨域拦在最外层,配好白名单保平安。"

相关推荐
思考着亮32 分钟前
5.数据库ORM_连接池_自动事务_增删改查高级语法与字典解包
后端
叫我:松哥1 小时前
基于flask仿小米商城管理系统,使用flask开的一个商场网站
数据库·后端·python·flask
Wang's Blog1 小时前
Vibe Coding一人即团队系列35: 基于Claude Code的Spring Boot项目初始化实践
java·spring boot·后端
2601_962065251 小时前
从零创建一个 Django 项目
后端·python·django
Elastic 中国社区官方博客2 小时前
从建议到修复的 4 个阶段:使用 Elastic Workflows 实现人在回路中的自动化
运维·数据库·人工智能·后端·elasticsearch·ai·自动化
码视野2 小时前
基于 Spring Boot + Vue3 的【城市地下燃气管网微泄漏感知与相邻地下空间燃爆预警中台】设计与实现(含PRD/三端高保真源码/大屏)
java·前端·人工智能·spring boot·后端
Profile排查笔记3 小时前
指纹浏览器手机版怎么选?从本地 App 到云端 Android 的实现方式解析
前端·人工智能·后端·自动化
jufeng13073 小时前
STM32F103 IAP 实战:串口 Bootloader 分区升级,掉电断电不白写
后端
Lost of 程序猿3 小时前
ASP.NET Core 多租户架构深度实战:一套系统,管理一支船队
后端·架构·asp.net