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

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

相关推荐
刚子编程9 小时前
我用 ASP.NET Core 做了个水稻病虫害检查系统
后端·asp.net
谢亮_vipxieliang9 小时前
用 PHP 构建轻量级 REST API:从路由到鉴权的完整实践
开发语言·后端·php
码事漫谈11 小时前
三步改掉 AI 味,附可直接复制的去 AI 味提示词
后端
IT_陈寒11 小时前
Redis卡顿的锅,这次真不是大key的错
前端·人工智能·后端
可乐鸡翅yeah_12 小时前
video.js 集成 hls.js 开发 M3U8 播放器,新手高频踩坑
开发语言·前端·javascript·后端·ecmascript·m3u8·音视频在线播放
程序猿_极客12 小时前
【免费】分享一套优质的基于SpringBoot的服装商城管理系统的设计与实现(带可视化图表、协同过滤功能),源码+文档+视频详解(讲解)
java·spring boot·后端·服装商城管理系统
明月_清风12 小时前
面对陌生的 GitHub 项目无从下手?这 4 个网站帮你快速读懂源码
前端·后端·github
bug菌13 小时前
🤔同事突然问我:Spring的注解 @Component 和 @Service 有何不同?
java·spring boot·后端
leobertlan13 小时前
痛苦系列 | DSP-02 频域切片:DTFT与DFT的探索
android·后端