FastAPI:(10)中间件与CORS

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.
相关推荐
从零开始学习人工智能4 小时前
基于FastAPI与Selenium的智能开关状态管理系统实践
selenium·adb·fastapi
严不鸽5 小时前
【Gin框架】中间件
中间件·gin
Python私教1 天前
FastAPI本地文档的定制技巧
fastapi
想躺平的咸鱼干2 天前
用idea进行数据同步
java·ide·后端·elasticsearch·中间件·intellij-idea
沛沛老爹3 天前
Celery+fastAPI/Flask实现高性能应用
python·flask·fastapi·celery·web框架集成
RexTechie4 天前
Spring Cloud Alibaba 中间件
java·spring cloud·中间件
RexTechie4 天前
Spring Cloud 原生中间件
spring·spring cloud·中间件
浠寒AI5 天前
【FastAPI高级实战】结合查询参数与SQLModel Joins实现高效多表查询(分页、过滤、计数)
fastapi
代码的知行者5 天前
分布式数据库中间件-Sharding-JDBC
数据库·分布式·中间件