当我们使用 FastAPI 构建 API 时,每个来自客户端的请求在到达实际的端点(即处理请求的函数)之前,都会先经过一个处理管道。这就是中间件发挥作用的地方。
中间件是一段代码,它会在请求到达端点之前运行,并在响应发送回去之后再次运行。它的主要作用包括:
- 检查或修改传入的请求。
- 添加额外的处理逻辑,如日志记录、身份验证和压缩。
- 调整或监控传出的响应。
!<a href="https://media.geeksforgeeks.org/wp-content/uploads/20250822094314148282/middlewareinfastapi.webp">middlewareinfastapi中间件示意图
中间件有两项主要任务:
- 在请求到达端点之前运行某些逻辑。
- 在响应离开端点之后运行某些逻辑。
为什么我们要使用中间件?
中间件允许我们自动对每个请求和响应应用功能,从而避免了在路由中编写重复的代码。这能让我们的应用程序保持整洁,更易于维护,且行为更加一致。
在 FastAPI 中添加中间件
以下是我们在 FastAPI 中添加中间件的语法:
> app.add_middleware(MiddlewareClass, options)
参数说明:
- MiddlewareClass: 我们想要使用的中间件(例如 CORSMiddleware)。
- options: 该中间件的配置项(例如 alloworigins, minimumsize 等)。
我们只需要在定义路由之前调用 app.add_middleware() 即可。
中间件通常分为两类:
- 内置中间件
- 自定义或用户定义的中间件
FastAPI 中的内置中间件
FastAPI(通过 Starlette)提供了几个我们可以直接使用的内置中间件。让我们通过示例逐一了解它们。
1. CORSMiddleware(跨域资源共享)
当前端(React、Angular、Vue)和 FastAPI 后端运行在不同的域或端口上时(例如 localhost:3000 和 localhost:8000),浏览器出于安全考虑会阻止这些跨域请求。CORS 中间件通过允许特定的域访问 API 来解决这个问题,从而实现前端与后端的顺畅通信。
示例: 让我们来看看如何在 FastAPI 中启用 CORS,以便前端可以在不被阻止的情况下与后端通信。
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
# 创建 FastAPI 应用
app = FastAPI()
# 添加 CORS 中间件
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 定义一个路由
@app.get("/")
def home():
return {"message": "CORS enabled!"}
输出结果
当我们在浏览器中访问 http://127.0.0.1:8000/ 时,我们将看到:
!<a href="https://media.geeksforgeeks.org/wp-content/uploads/20250821131813506562/CORSmiddlewareOutput.png">CORSmiddlewareOutputCORS 中间件输出结果
现在,任何前端应用都可以访问此 API 而不会被阻止。
代码解析:
- alloworigins=["*"] 允许所有域访问我们的 API,allowcredentials=True 允许发送 Cookie 和身份验证标头。
- allowmethods=[""] 允许所有 HTTP 方法(GET, POST, PUT, DELETE 等),allowheaders=[""] 允许请求中的所有标头。
- @app.get("/"): 在 / 处定义了一个简单的 GET 路由。
- def home(): 返回一个 JSON 响应以确认 CORS 已启用。
2. GZipMiddleware(响应压缩)
当我们的 API 需要发送大型响应(例如大型 JSON 数据集)时,数据传输可能会耗时较长并消耗更多带宽。GZipMiddleware 会在将响应发送给客户端之前自动压缩这些响应,使其体积更小、传输更快且效率更高。
示例: 这个示例展示了如何使用 GZipMiddleware 自动压缩大型响应,从而节省带宽。
from fastapi import FastAPI
from fastapi.middleware.gzip import GZipMiddleware
app = FastAPI()
# 添加 GZip 中间件
app.add_middleware(GZipMiddleware, minimum_size=1000)
@app.get("/large-data")
def get_data():
return {"data": "x" * 2000} # 一个大型响应
输出结果
当我们打开 /large-data 时,服务器会在发送响应之前对其进行压缩。浏览器会自动解压并显示:
!<a href="https://media.geeksforgeeks.org/wp-content/uploads/20250821145657306711/GZipMiddlewareOutput.jpg">GZipMiddlewareOutputGZip 中间件输出结果
代码解析:
- minimum_size=1000: 只有大于 1000 字节的响应才会被压缩(这是为了避免对小响应进行不必要的压缩而增加开销)。
- @app.get("/large-data"): 定义了一个 API 端点 /large-data。
- return {"data": "x" * 2000}: 返回一个大约 2000 个字符的大型 JSON 响应。因为它大于 1000 字节,所以在发送给客户端之前会自动被压缩。
3. TrustedHostMiddleware(限制允许的主机)
当应用部署到生产环境后,我们的 FastAPI 应用可能会被