FastAPI 核心知识梳理(二):Request、Response 、中间件与依赖系统完全指南
本文介绍了FastAPI中request对象的核心用法,包括获取请求头、路径参数、查询参数、请求体和Cookie等常见操作。通过代码示例详细展示了如何利用request.headers、request.path_params、request.query_params等方法提取各类请求数据,并讲解了Cookie的自动携带特性和生命周期设置。文章还提及了response_model的概念,用于约束和格
上篇:FastAPI 核心知识梳理:路由、参数传递与文件上传完全指南
1. request 对象
概念:客户端向服务器发送的各种请求的封装。
可以通过request对象获取:请求头,各种参数如路径参数、请求体、查询参数,以及cookie等。
1.1. 获取header
request.headers.get()
示例:如何获取请求头。
from fastapi import APIRouter, Request
request_router = APIRouter()
@request_router.get("/headers/")
async def get_request_headers(request: Request):
# 获取请求头
print(f"请求头: {request.headers}")
# 获取请求方法
print(f"请求方法: {request.method}")
# 获取请求头中的Content-Type
content_type = request.headers.get("Content-Type")
return {
"content_type": content_type
}
运行结果:
请求头: Headers({'user-agent': 'PostmanRuntime/7.53.0', 'accept': '*/*', 'postman-token': '50813957-e7f9-4ab9-9454-1e77c7b2b2df', 'host': '127.0.0.1:8888', 'accept-encoding': 'gzip, deflate, br', 'connection': 'keep-alive'})
请求方法: GET
并返回content_type值为:null
1.2. 获取路径参数
request.path_params.get()
示例:如何获取路径参数
@request_router.get("/path/{name}")
async def get_request_path_variable(request: Request):
print(f"请求参数: {request.path_params}")
# 通过path_params获取路径参数,参数名为name
name = request.path_params.get("name")
return{
"name": name
}
在路径后面补充参数zhangsan,返回"name":zhangsan![![[Pasted image 20260413201528.png]]](https://i-blog.csdnimg.cn/direct/a5e9b847e8aa4c2faf1086c74d9405f2.png)
1.3. 获取查询参数
request.query_params.get()
示例:获取查询参数
@request_router.get("/param/")
async def get_request_param(request: Request):
print(f"请求参数: {request.query_params}")
# 通过query_params获取查询参数,参数名为name
name = request.query_params.get("name")
return{
"name": name
}
填写param字段:key:name,value:lisi,返回参数名和参数值。![![[Pasted image 20260413201715.png]]](https://i-blog.csdnimg.cn/direct/4d6760d8f3f84407ac0665d5ec520c93.png)
1.4. 获取请求体
request.json()
示例:获取请求体
@request_router.post("/body/")
async def get_request_body(request: Request):
body = await request.json()
return{"body": body}
填写body内容,最后返回json![![[Pasted image 20260413203431.png]]](https://i-blog.csdnimg.cn/direct/bcbc0193e08c4f42ada9ea56648797db.png)
1.5. cookie
Cookie 本质上是“服务器让浏览器帮忙存数据,并在之后自动带回来”。
作用:标识用户
Cookie 的作用是“在客户端(浏览器)保存一点数据,并在后续请求中自动带上”,从而让服务器能够识别用户身份或记录状态。简单说,它解决的是 HTTP 无法记住用户的问题。
原理:服务器发 → 浏览器存 → 浏览器带 → 服务器识别
- 第一步,服务器在响应中通过 Set-Cookie 把一段数据发给浏览器,比如一个 session_id。
- 第二步,浏览器会把这个 Cookie 保存下来。
- 第三步,之后浏览器每次请求同一个网站时,都会自动在请求头中带上 Cookie,比如:Cookie: session_id=abc123。
- 第四步,服务器通过这个 session_id 就可以识别用户,比如查数据库知道你已经登录了。
特点
- 自动携带:浏览器会自动带上,不需要手动处理。
- 存储在客户端:数据保存在浏览器中。
- 有大小限制:一般每个 Cookie 不能太大(通常几 KB)。
- 可以设置生命周期:可以是会话级(关闭浏览器就没了)或长期有效。
- 有安全属性:比如
HttpOnly(防止被 JS 读取)、Secure(只在 HTTPS 传输) - 主要用于:检验用户登录状态、保存用户偏好,以及简单的跟踪信息(比如访问记录)。
设置Cookie
服务器生成Cookie,所以需要用到Response对象。
response.set_cookie(key="xxxx",value="xxxx")
设置Cookie示例:
@request_router.post("/cookie/set")
async def set_cookie(response : Response):
"""
设置Cookie
:param response: 响应对象
:return:
""" # max_age 是秒数,设置Cookie的过期时间,60秒后过期
response.set_cookie(key="session-id", value="1234567890",max_age=60)
return {
"message": "Cookie设置成功"
}
获取Cookie
每次访问浏览器,都会在请求头中带上Cookie,属于请求数据,可以用request对象。
request.cookies.get()
获取Cookie示例:
@request_router.get("/cookie/get")
async def get_cookie(request: Request):
"""
获取Cookie
:param request: 请求对象
:return:
""" cookie = request.cookies.get("session-id")
return {
"cookie": cookie
}
值得一提的是,超过cookie的最大生命周期(本例中设置的是60s),便不能获取到cookie了,此时cookie为null。
1.6. 在浏览器中如何查看header或者cookie?
- 按住 F12 或者右键点击检查——> 点击网络——> 选择方法——> 点击Cookie。
- 点击标头,可以看到头信息。

1.7. response-model
response_model 是 FastAPI 用来“约束和格式化返回数据”的工具。简单理解就是:你可以指定接口“最终返回的数据结构长什么样”,FastAPI 会自动帮你过滤、校验并输出。
默认情况下,你 return 什么,FastAPI 就返回什么。但在真实开发中,这样有两个问题:
第一,可能返回多余字段(比如数据库里的敏感信息);
第二,返回结构不统一,不方便前端使用。
response_model 的作用就是解决这些问题。你可以定义一个 Pydantic 模型,然后在接口中声明 response_model,这样 FastAPI 会做三件事:
1)只保留模型中定义的字段(多余的会被自动过滤)
2)自动校验返回数据类型
3)生成更清晰的接口文档(Swagger)
response-model使用实例1:
from fastapi import APIRouter
from pydantic import BaseModel, Field
response_router = APIRouter()
class UserOut(BaseModel):
id: int
name: str = Field(default="zhangsan",max_length=20,min_length=6)
email: str = Field(default="zhangsan@example.com", pattern=r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
@response_router.get("/response-model",response_model=UserOut)
async def get_response():
return{
"id": 1,
"name": "zhangsan",
# 邮箱少写了 `@` 符号
"email": "zhangsanexample.com"
}
在get_response()方法中,我们返回了错误的邮箱格式,此时设置的response_model 会在返回响应时校验数据,如果不符合模型定义,会报错并阻止错误数据返回给客户端。![![[Pasted image 20260413221117.png]]](https://i-blog.csdnimg.cn/direct/89ec49ecbb1c4feb9673c2c66947bab2.png)
response_model的其他用法:
- 可以传入一个对象,而输出另一个对象。比如传入一个User对象包括密码,输出的时候就可以利用response_model隐去密码字段。
- response 对象的属性: response_model_include(set)->({“XXX” , “XXX”})包括字段,response_model_exclude排除字段。
2. response 对象
2.1. HTMLResponse:可以在页面渲染html格式。
@response_router.get("/html_response")
async def get_html_response():
return HTMLResponse('<h1>Hello HTMLResponse</h1>')
2.2. RedirectResponse:用于重定向。
@response_router.get("/redirect_response")
async def get_redirect_response():
return RedirectResponse(url="https://baidu.com")
2.3. FileResponse:用于文件下载。
@response_router.get("/file_response")
async def get_file_response():
path = os.path.join(os.path.dirname(__file__), "logo.png")
return FileResponse(path)
3. 中间件 middleware
3.1. 概念
请求到达目标API之前,将请求拦截。中间件一旦建立,项目中的所有请求都会经过该中间件。
3.2. 应用场景
- 认证:用户登录
- 鉴权:访问控制
- 日志管理
- 数据清洗:数据合法性验证
- 限流(流控):QPS(每秒查询数),防止QPS过高击穿网站
3.3. 实现
middleware.urls.py:
from fastapi import APIRouter
middleware_router = APIRouter()
@middleware_router.get("/one")
async def action():
print("中间件执行中")
return {"message": "中间件执行中"}
main.py:
from fastapi import FastAPI, Request
from fastapi_review.apps.middleware.urls import middleware_router
app = FastAPI()
# include 路由
app.include_router(middleware_router, prefix="/middleware", tags=["中间件管理模块"])
@app.middleware("http")
async def m1(request: Request, call_next):
"""
:param request: 请求对象
:param call_next: 将请求继续向下传递的对象
:return: """
print("执行中间件m1前操作")
response = await call_next(request)
print("执行中间件m1后操作")
return response
@app.middleware("http")
async def m2(request: Request, call_next):
print("执行中间件m2前操作")
response = await call_next(request)
print("执行中间件m2后操作")
return response
中间件从下到上执行,先执行m2再执行m1:![![[Pasted image 20260417222434.png]]](https://i-blog.csdnimg.cn/direct/c11dcc0c6fda4217a7d4ad279f4bc242.png)
执行过程:
进入 m2
→ 进入 m1
→ 执行 API
← 返回 m1
← 返回 m2
输出:
4. 依赖系统
FastAPI的依赖系统是一种自动“管理和注入资源”的机制。FastAPI 的依赖系统允许你在路径操作函数执行前,先运行另一个函数,并把那个函数的返回值“注入”到你的路径操作函数里。
4.1. 为什么要注入依赖
假设你正在做一个管理系统,有一下接口:
- /api/users —— 查看用户列表
- /api/orders —— 查看订单列表
- /api/products —— 查看商品列表
这三个接口的共同点就是,都需要做分页查询,都需要分页参数(offset、limit)来查询数据库中的数据。
如何不使用依赖,我们的代码将会变得冗余且难以维护:
from fastapi import APIRouter
dependency_router = APIRouter()
# 3 个接口都需要分页参数
@dependency_router.get("/users")
async def list_users(offset: int = 0, limit: int = 10):
return query_users(offset, limit)
@dependency_router.get("/orders")
async def list_orders(offset: int = 0, limit: int = 10):
return query_orders(offset, limit)
@dependency_router.get("/products")
async def list_products(offset: int = 0, limit: int = 10):
return query_products(offset, limit)
痛点:
- 每个接口都要写一遍
offset: int = 0, limit: int = 10 - 如果某天要改成
limit: int = 20,要改 3 个地方 - 如果某天要加
max_limit=100的限制,3 个地方都要加
4.2. 如何使用依赖
- 创建依赖系统(普通的函数)
- 在路由函数中使用Depends注入依赖
from fastapi import APIRouter, Depends, Query
dependency_router = APIRouter()
# 1.创建依赖系统(普通的函数)
def get_page_params(offset: int = Query(0, description="分页偏移量"), limit: int = Query(10, description="分页大小")):
return {"offset": offset, "limit": limit}
# 2.在路由函数中使用Depends注入依赖
@dependency_router.get("/users/")
async def list_users(page=Depends(get_page_params)):
# FastAPI 自动做了这件事:
# 1. 发现 get_page_params 需要 offset 和 limit
# 2. 从 URL 的 ?offset=xxx&limit=xxx 中取值
# 3. 调用 get_page_params(offset, limit)
# 4. 把返回值赋给 page
return {
"offset": page["offset"],
"limit": page["limit"]
}
访问:http://127.0.0.1:8888/dependency/users
offset和limit就是默认值。
访问http://127.0.0.1:8888/dependency/users/?offset=20&limit=5
offset和limit就是设定的值。
4.3. 依赖系统的三大作用
| 作用 | 没有依赖系统 | 有依赖系统 |
|---|---|---|
| 消除重复代码 | 每个接口都写一遍相同的参数定义 | 定义一次,处处复用 |
| 集中管理逻辑 | 校验规则、默认值散落在各个接口 | 所有逻辑集中在依赖函数中 |
| 自动解析注入 | 手动从 request 对象里抠参数 |
FastAPI 自动解析、转换、校验、注入 |
4.4. 常见应用场景
| 场景 | 示例 |
|---|---|
| 分页参数 | def pagination(offset, limit): ... |
| 用户认证 | def get_current_user(token): ... |
| 数据库连接 | def get_db(): ... |
| 权限校验 | def require_admin(user): ... |
| 请求限流 | def rate_limit(): ... |
4.5. 关键要点
- 依赖函数就是普通函数— 但参数必须用
Query()、Header()等声明来源 Depends是连接器 — 告诉 FastAPI “这个参数的值,请调用那个函数来获取”- 依赖系统的本质:FastAPI 负责自动化 — 解析 HTTP 请求 → 调用依赖函数 → 注入返回值
更多推荐
所有评论(0)