Cookie、Header 与额外数据类型
本教程共 50 篇 · 第 18 篇 · 更新于 2026-08-12 · 约 9 分钟阅读
本节目标:学会用
Cookie和Header读取请求里的 Cookie 与请求头,并了解 FastAPI 对 datetime、UUID、bytes、Decimal 等类型的自动转换与校验。
除了路径参数、查询参数、请求体,HTTP 请求里还有两类常见数据:Cookie 和请求头(Header)。另外,FastAPI 借助 Pydantic,还能直接处理许多”非基础”的 Python 数据类型。本章把它们一起讲清楚。
18-1 用 Cookie 读取请求里的 Cookie
读取 Cookie 的方式和读取查询参数几乎一样,只是把 Query 换成 Cookie。你必须显式用 Cookie,否则 FastAPI 会把它当成查询参数。
from fastapi import Cookie, FastAPI
app = FastAPI()
@app.get("/items/")
async def read_items(ads_id: str | None = Cookie(default=None)) -> dict:
return {"ads_id": ads_id}
这里 ads_id 从客户端请求携带的 Cookie 里读取。没传就是 None。Cookie 和 Query、Path 是”姐妹类”,都支持默认值、校验规则那一套。
Note在浏览器里,Cookie 由浏览器底层管理,JavaScript 不能随意触碰。所以你在
/docs里填了 Cookie 点”Execute”,因为文档界面是 JS 发的请求,Cookie 实际发不出去,会看到像没传值一样的报错。这不是代码错,用真实客户端(如前端 fetch、requests)测试就好。
如何用 Response.set_cookie(...) 下发 Cookie,在第 15 章已经讲过,这里不再赘述。
18-2 用 Header 读取请求头
读请求头同理,用 Header:
from fastapi import FastAPI, Header
app = FastAPI()
@app.get("/items/")
async def read_items(user_agent: str | None = Header(default=None)) -> dict:
return {"User-Agent": user_agent}
访问后,返回的 JSON 里就带有浏览器的 User-Agent 信息。
18-3 下划线自动转连字符
HTTP 请求头的名字用连字符,比如 X-Token、User-Agent。可 Python 变量名不允许有连字符,所以你写 x_token,FastAPI 会自动把它映射成 X-Token。
from fastapi import FastAPI, Header
app = FastAPI()
@app.get("/items/")
async def read_items(
x_token: str | None = Header(default=None),
user_agent: str | None = Header(default=None),
) -> dict:
return {"X-Token": x_token, "User-Agent": user_agent}
转换规则对照:
| Python 变量名 | 对应的 HTTP 头 |
|---|---|
x_token | X-Token |
user_agent | User-Agent |
content_type | Content-Type |
HTTP 头本身不区分大小写,所以你用 snake_case(x_token)写法完全没问题,不用去大写首字母。
Tip极少数情况下你想关闭这个自动转换,可以写
Header(default=None, convert_underscores=False)。但注意,有些 HTTP 代理和服务器禁止使用带下划线的头,一般不建议关。
18-4 接收重复的请求头
有的头可能在一个请求里出现多次(比如 Set-Cookie)。用 list 类型声明,FastAPI 会把所有值收集成一个列表返回给你。
from fastapi import FastAPI, Header
app = FastAPI()
@app.get("/items/")
async def read_items(x_token: list[str] | None = Header(default=None)) -> dict:
return {"X-Token values": x_token}
如果客户端发了:
X-Token: foo
X-Token: bar
响应就是 {"X-Token values": ["foo", "bar"]}。
18-5 额外数据类型:datetime
除了 int、float、str、bool 这些基础类型,FastAPI 还支持一大批”额外数据类型”,而且照样享有编辑器支持、自动转换、校验和文档生成。
datetime.datetime 表示一个具体时刻。客户端传字符串(ISO 8601 格式),FastAPI 自动转成 Python 的 datetime 对象。
from datetime import datetime
from fastapi import FastAPI
app = FastAPI()
@app.get("/events/")
async def read_events(started_after: datetime | None = None) -> dict:
if started_after:
return {"started_after": started_after.isoformat()}
return {"started_after": None}
请求 /events/?started_after=2024-09-15T15:53:00+08:00,函数里拿到的 started_after 就是真正的 datetime 对象,你可以直接调用 .isoformat() 等方法做日期运算。同样的规则也适用于 datetime.date(只含日期)和 datetime.time(只含时刻)。
18-6 额外数据类型:UUID
UUID 是通用的唯一标识符,很多数据库用它当主键。客户端传字符串形式的 UUID,FastAPI 自动转成 Python 的 uuid.UUID 对象,并会校验格式是否合法。
import uuid
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: uuid.UUID) -> dict:
return {"item_id": item_id, "item_id_type": type(item_id).__name__}
访问 /items/9c2c1b9e-0b3a-4f1e-8d2a-1a2b3c4d5e6f,item_id 已是 UUID 实例,且格式错误会被直接拦截。
18-7 额外数据类型:bytes 与 Decimal
bytes 表示二进制数据。在请求和响应里它表现为字符串,但 FastAPI 会按二进制处理,生成的 JSON Schema 里标记为 binary 格式。
Decimal 是高精度小数(避免浮点误差),处理方式和 float 类似,适合金额这类对精度敏感的数据。
from decimal import Decimal
from fastapi import FastAPI
app = FastAPI()
@app.get("/calc/")
async def calc(amount: Decimal | None = None) -> dict:
if amount is None:
return {"amount": None}
return {"amount": str(amount), "doubled": str(amount * 2)}
请求 /calc/?amount=10.05,amount 是 Decimal 类型,做 amount * 2 精确计算不会丢精度。
18-8 综合示例
把几种额外类型放在一起,体会一下”声明即校验、调用即得对象”的爽感:
from datetime import datetime
from decimal import Decimal
from uuid import UUID
from fastapi import FastAPI
app = FastAPI()
@app.put("/items/{item_id}")
async def update_item(
item_id: UUID,
start_time: datetime | None = None,
price: Decimal | None = None,
) -> dict:
result = {
"item_id": str(item_id),
"start_time": start_time.isoformat() if start_time else None,
"price": str(price) if price else None,
}
return result
item_id 会被校验成合法 UUID,start_time 转成 datetime,price 转成 Decimal。凡是不符合格式的请求,FastAPI 自动返回 422 校验错误,你一行校验代码都不用写。
18-9 综合示例:读取请求头、Cookie 并处理额外类型
把 Cookie、Header、UUID、datetime 放到一个接口里,看 FastAPI 如何一站式解析:
from datetime import datetime
from uuid import UUID
from fastapi import Cookie, FastAPI, Header
app = FastAPI()
@app.post("/upload/{task_id}")
async def upload(
task_id: UUID,
token: str | None = Header(default=None),
session: str | None = Cookie(default=None),
happened_at: datetime | None = None,
) -> dict:
return {
"task_id": str(task_id),
"token": token,
"session": session,
"happened_at": happened_at.isoformat() if happened_at else None,
}
请求时,URL 里的 task_id 被校验成 UUID,token 从 Token 请求头读取(变量名 token 自动对应 Token 头),session 从 Cookie 读取,happened_at 从查询参数解析成 datetime。函数体内拿到的全是可以直接用的 Python 对象,不用自己写任何转换或校验代码。
Tip额外数据类型还有
datetime.timedelta(时长,在 Pydantic v2 中以 ISO 8601 时长字符串传输,如P1DT1H1M1S)、frozenset(去重集合)等。完整清单可查 Pydantic 官方数据类型文档。记住一个原则:能用标准 Python 类型声明,就别自己手写字符串解析。
需要强调:这些额外类型的”自动转换”只发生在 FastAPI 接收请求参数(路径、查询、Header、Cookie、请求体字段)的时候。函数内部你拿到的已经是真正的 Python 对象,可以直接调用对象的方法,比如对 datetime 做加减、对 Decimal 做精确运算、对 UUID 取 .hex 等。这也意味着,如果你的客户端传了一个格式不对的 UUID 或日期字符串,FastAPI 会在进入函数前就返回 422 校验错误,你的业务代码根本不会被调用,从而避免了”脏数据进业务逻辑”的麻烦。
18-10 小结
Cookie、Header 和额外数据类型,让接口能承载更丰富的信息:
- 用
Cookie(...)读取请求里的 Cookie,用Header(...)读取请求头。 Header自动把变量名下划线转成头的连字符,大小写不敏感。- 用
list[str]接收重复出现的请求头。 - 额外数据类型(如
datetime、UUID、bytes、Decimal)享受和基础类型一样的自动转换、校验、文档生成。 - 这些类型在请求里以字符串呈现,进入函数后已是对应 Python 对象,直接拿来用即可。