FastAPI:(10)中间件与CORS
由于CSDN无法展示「渐构」的「#d,#e,#t,#c,#v,#a」标签,推荐访问我个人网站进行阅读:Hkini
「渐构展示」如下:
#c 概述 文章内容概括
FastAPI中间件与CORS 中间件 CORS 请求/响应拦截 全局功能 记录请求时间 认证检查 非业务逻辑 跨域资源共享 允许来源 允许方法 允许头信息 特定域名 通配符*
1.中间件
#d 中间件
「中间件」是一个在每个 HTTP 请求和响应过程之间运行的组件,它可以在请求到达具体路由处理函数(endpoint)之前 执行逻辑,也可以在响应返回客户端之后执行逻辑。中间件主要用于执行与业务逻辑无关但对所有路由有效的功能,例如:请求日志记录、用户认证、跨域处理、安全检查、请求/响应修改等。
重要特征:
- 特征1:中间件在请求与响应之间全局拦截并处理,不绑定于单个路由
- 特征2:具有前处理(request)和后处理(response)两段生命周期
- 特征3:在框架级别工作,适合抽象通用逻辑(如日志、安全、限流)
- 特征4 :必须使用
@app.middleware("http")
装饰器注册 - 特征5 :响应必须返回
Response
对象,否则请求链会断裂
#e 记录所有请求响应时间(正例) 中间件
例子描述
一个中间件记录每个 API 请求的处理耗时,用于性能监控。逻辑独立于具体业务,但对所有请求有效,对性能调优有重要价值。
特征对比
- ✅ 全局拦截请求和响应
- ✅ 与业务无关但功能通用
- ✅ 使用标准装饰器注册
- ✅ 前处理获取时间,后处理记录耗时
- ✅ 合理返回
Response
对象
python
from fastapi import FastAPI, Request
import time
app = FastAPI()
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
@app.get("/hello")
async def hello():
return {"message": "Hello, world!"}
#e 用户认证令牌(正例) 中间件
例子描述
中间件解析请求头中的认证 token,如果验证失败,直接返回 401,不进入业务逻辑。适用于所有需要权限控制的路由。
特征对比
- ✅ 中间件作用于所有路径,统一处理权限
- ✅ 请求处理前拦截非法访问
- ✅ 返回适当响应
- ✅ 保持逻辑与控制器解耦
- ✅ 使用框架标准语法
python
from fastapi import FastAPI, Request, Response
from fastapi.responses import JSONResponse
app = FastAPI()
@app.middleware("http")
async def check_token(request: Request, call_next):
token = request.headers.get("Authorization")
if token != "Bearer secrettoken":
return JSONResponse(status_code=401, content={"detail": "Unauthorized"})
response = await call_next(request)
return response
@app.get("/secure-data")
async def secure_data():
return {"data": "Top secret content"}
#e 中间件中处理具体业务逻辑(反例) 中间件
例子描述
某电商网站开发者在中间件中写入了订单处理逻辑:如果路径包含 /buy
,就解析请求体并写入订单数据库。这种做法将中间件强行绑定业务逻辑,破坏职责边界,导致系统难以维护。
特征对比
- ❌ 中间件滥用于业务逻辑处理
- ❌ 没有保持抽象和职责分离
- ❌ 逻辑非全局通用,适配性差
- ❌ 不符合中间件设计初衷
- ❌ 后续维护困难,隐藏副作用
python
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
@app.middleware("http")
async def bad_order_logic(request: Request, call_next):
if request.url.path.startswith("/buy"):
json_body = await request.json()
# ❌ 直接写入数据库(模拟)
print(f"Inserting order: {json_body['item']} to DB")
return JSONResponse({"msg": "Order processed in middleware"}) # 跳过 endpoint
return await call_next(request)
@app.post("/buy")
async def buy():
return {"msg": "Order endpoint reached"}
#e 官网例子(正例) 中间件
添加「自定义请求头」,中间件函数接收如下参数:
request
.- 一个函数
call_next
它将接收request
作为参数.- 这个函数将
request
传递给相应的 路径操作. - 然后它将返回由相应的_路径操作_生成的
response
.
- 这个函数将
- 然后可以在返回
response
前进一步修改它.
python
import time
from fastapi import FastAPI, Request
app = FastAPI()
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.perf_counter()
response = await call_next(request)
process_time = time.perf_counter() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
2.CORS(跨域资源共享)
#d CORS跨域资源共享
CORS 是一种浏览器安全机制,允许服务器声明哪些"源"(协议+域名+端口)可以访问该服务器资源。当前端 JavaScript 从一个源请求另一个源的资源时(跨域请求),浏览器会根据服务器是否设置了合适的 CORS 响应头来决定是否允许该请求。FastAPI 提供了内置的 CORSMiddleware
用于实现 CORS 策略。
重要特征:
- 特征1:仅针对浏览器发起的跨域请求生效(如前端请求 API)
- 特征2:服务器必须明确声明允许的来源、方法、头信息等
- 特征3 :需通过中间件(如
CORSMiddleware
)统一配置 - 特征4:允许细粒度配置(如允许哪些域、是否发送 cookies)
- 特征5:浏览器会在跨域敏感操作前先发起「预检请求(OPTIONS)」
#e 一个前端访问用户数据(正例) CORS跨域资源共享
例子描述
一个单页前端应用(如 React)部署在 http://localhost:3000
,后端 API 使用 FastAPI 部署在 http://localhost:8000
,通过配置 CORSMiddleware
显式允许前端访问 /users
路由。
特征对比
- ✅ 跨源请求明确存在
- ✅ 通过中间件配置允许来源
- ✅ 浏览器可成功访问 API
- ✅ 满足 CORS 的所有响应头要求
- ✅ 精细控制跨域行为
python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# CORS 配置
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"], # 允许 React 应用访问
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/users")
def read_users():
return [{"username": "alice"}, {"username": "bob"}]
#e 多个第三方站点访问(正例) CORS跨域资源共享
例子描述
气象服务 API 面向多平台开放,允许来自多个来源(如 *.weather.com
, *.edu.cn
)请求公开天气数据。通过 allow_origins=["*"]
配置放开访问权限。
特征对比
- ✅ 明确设置开放跨域策略
- ✅ 面向所有来源共享资源
- ✅ 没有访问控制私密性需求
- ✅ 使用 FastAPI 的中间件配置正确
- ✅ 满足公开 API 的通用需求
python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# CORS 配置:允许所有来源
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 开放 API 给所有客户端
allow_methods=["GET"],
allow_headers=["*"],
)
@app.get("/weather")
def get_weather():
return {"city": "Beijing", "temp": 26}
#e 合法前端请求被拦截(反例) CORS跨域资源共享
例子描述
开发者搭建了一个前后端分离的项目,但未在 FastAPI 中配置 CORS 中间件,导致浏览器在请求接口时出现跨域错误(如 CORS policy blocked: No 'Access-Control-Allow-Origin' header
)。
特征对比
- ❌ 跨源访问未被允许
- ❌ 无任何中间件配置响应头
- ❌ 浏览器阻止请求,安全机制生效
- ❌ 不符合 CORS 正确配置要求
- ❌ 用户体验受损、功能失效
python
from fastapi import FastAPI
app = FastAPI()
@app.get("/private")
def read_private_data():
return {"secret": "123456"}
报错:
json
Access to fetch at 'http://localhost:8000/private' from origin 'http://localhost:3000' has been blocked by CORS policy.