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.
相关推荐
在未来等你11 小时前
RabbitMQ面试精讲 Day 5:Virtual Host与权限控制
中间件·面试·消息队列·rabbitmq
Whoisshutiao2 天前
网安-中间件-Redis未授权访问漏洞
中间件
cts6182 天前
全文检索官网示例
python·全文检索·fastapi
半新半旧3 天前
FastAPI中间件
中间件·fastapi
爱吃羊的老虎4 天前
【后端】FastAPI的Pydantic 模型
数据库·后端·python·fastapi
Elastic 中国社区官方博客4 天前
使用 FastAPI 构建 Elasticsearch API
大数据·数据库·python·elasticsearch·搜索引擎·全文检索·fastapi
陈小桔5 天前
SQLALchemy
python·fastapi
努力找工作的OMArmy5 天前
分布式数据库中间件ShardingSphere
数据库·分布式·中间件
alpszero5 天前
使用UV管理FastAPI项目
fastapi·uv
**梯度已爆炸**6 天前
Python Web框架详解:Flask、Streamlit、FastAPI
python·flask·fastapi·streamlit