首页
/ FastAPI Header 请求头参数详解:声明、自动下划线转换与重复请求头处理

FastAPI Header 请求头参数详解:声明、自动下划线转换与重复请求头处理

2026-09-07 14:42:18作者:宣海椒Queenly

HTTP 请求头(Headers)广泛用于传递认证令牌、客户端信息、追踪标识等元数据。FastAPI 提供与 QueryPathCookie 完全一致的 Header 参数机制,让你能用 Python 惯用的 snake_case 命名安全地提取像 User-Agent 这样的标准请求头,并支持对重复请求头的自动列表化处理。阅读本文后,你将掌握如何在 FastAPI 中导入并声明请求头参数、理解其将下划线自动转换为连字符(-)的工作原理、按需关闭该转换,以及接收同一请求头多次出现时的全部值。

本文主体对应仓库中的法语文档 docs/fr/docs/tutorial/header-params.md,示例代码均可直接运行,源码与测试目录中能找到完整的配套实现与验证用例。

什么是请求头参数,为什么需要 Header

HTTP 协议中,请求头(header)是请求行之后以 键: 值 形式携带的元数据,例如浏览器每次请求都会自动带上 User-AgentAccept 等标准请求头,业务上还常用 X-TokenAuthorization 等自定义头传递上下文。

在 FastAPI 中,声明请求头参数的方式与声明 QueryPathCookie 参数完全相同:把它作为路径操作函数的一个形参,并用 Header() 包裹类型注解即可。区别仅在于数据来源——Query 从 URL 查询字符串取值,Path 从 URL 路径模板取值,而 Header 从 HTTP 请求头中取值。

导入 Header

第一步是从 fastapi 中导入 Header,代码位于 docs_src/header_params/tutorial001_an_py310.py

from typing import Annotated

from fastapi import FastAPI, Header

app = FastAPI()

如果你使用的是旧式写法(不依赖 Annotated),语法同样受支持,仓库中同时保留了 tutorial001_py310.py 等纯类型注解版本的等价示例。

声明 Header 参数

接下来按照与 PathQueryCookie 相同的结构声明请求头参数。你可以设置默认值,也可以附加校验与元数据参数。例如读取客户端发送的 User-Agent 请求头:

@app.get("/items/")
async def read_items(user_agent: Annotated[str | None, Header()] = None):
    return {"User-Agent": user_agent}

这里声明了一个名为 user_agent、可选的 str 请求头参数:缺省时值为 None,传入时则回显其内容。

技术细节HeaderPathQueryCookie 的"姊妹"类,都继承自同一个公共基类 Param。从源码看,这一继承关系定义在 fastapi/params.py#L303class Header(Param),并通过 in_ = ParamTypes.header 标记参数属于 header 位置。同时要注意,当你从 fastapi 导入 QueryPathHeader 时,得到的实际上是返回特殊类的函数——真正的类定义见 fastapi/params.py,而 fastapi/param_functions.py#L701 中的 Header() 函数负责装配默认值、校验规则等参数并实例化返回。这种双层结构让你既能像调用函数一样书写参数,又能获得完整的类型检查支持。

重要提醒:声明请求头参数时必须显式使用 Header(),否则 FastAPI 会把该形参当作普通的查询参数(query parameter)处理——因为在 fastapi/dependencies/utils.py 的默认逻辑中,未指定 in_Param 会被归入 query 位置。这会造成数据永远无法从请求头中读到,接口行为与预期完全不符。

下划线到连字符的自动转换

Header 相比 PathQueryCookie 多提供了一项便利功能。绝大多数标准 HTTP 请求头的名称是用连字符(-)分隔的,如 User-AgentX-Forwarded-For;但 Python 中变量名里带 - 是非法的,写不出 user-agent 这样的形参名。

因此,默认情况下 Header 会把形参名中的下划线 _ 自动转换为连字符 -,再据此去提取并记录(document)对应的请求头。同时,HTTP 请求头本身不区分大小写,所以你可以放心使用 Python 标准命名风格(即 snake_case)。例如声明形参 user_agent,实际匹配的是 User-Agent 请求头——这正是上一节示例能够工作的原因,无需把代码写成 User_Agent 这样生硬的名字。

这一转换并不只发生在提取阶段。从 fastapi/dependencies/utils.py#L524 附近的实现可以看到,当参数使用了 Header 且未显式指定 aliasconvert_underscores 为真时,框架会执行 alias = param_name.replace("_", "-"),把转换后的名字作为别名用于解析与 OpenAPI schema 生成;在请求头来自 Headers 对象(如使用 Pydantic 模型聚合请求头)的场景中,fastapi/dependencies/utils.py#L793-L828 也实现了同样的 replace("_", "-") 逻辑并保持默认开启。

关闭自动转换:convert_underscores=False

如果由于某种原因你需要禁用下划线转连字符的自动转换,只需将 Headerconvert_underscores 参数设为 False。示例见 docs_src/header_params/tutorial002_an_py310.py

@app.get("/items/")
async def read_items(
    strange_header: Annotated[str | None, Header(convert_underscores=False)] = None,
):
    return {"strange_header": strange_header}

关闭后,名为 strange_header 的形参将原样匹配字面的 strange_header 请求头,而不会去找 strange-header。源码层面该选项的默认值定义在 Header() 函数签名(fastapi/param_functions.py#L761)与 Header 类构造器(fastapi/params.py#L316)中,均为 True,并被保存为字段属性供依赖解析阶段读取。

警告:在把 convert_underscores 设为 False 之前请三思——某些代理服务器与 HTTP 服务器会禁止使用含下划线 _ 的请求头,将其视为非法字段。此时若你仍希望用带下划线的请求头名,客户端发起的请求可能根本到不了你的应用。因此实践中更推荐保持默认的自动转换行为,让客户端发送连字符形式的请求头。

注意事项小结

  • 默认启用转换:user_agent → 匹配 User-Agent
  • convert_underscores=Falseuser_agent → 匹配字面的 user_agent
  • 请求头大小写不敏感,但接收方通常以首字母大写的连字符形式发送(如 User-Agent);
  • 生产环境中与反代、网关等中间层协作时,优先使用连字符风格,规避下划线被拦截的风险。

处理重复的请求头

HTTP 允许同一个请求头多次出现——即同名请求头携带多个值。这在 X-TokenAccept-* 等场景很常见。FastAPI 通过在类型注解中使用列表来接收重复请求头的全部值:声明后,框架会把该请求头的所有值合并成一个 Python list 返回给你。

例如,声明一个可能出现多次的 X-Token 请求头,完整示例见 docs_src/header_params/tutorial003_an_py310.py

@app.get("/items/")
async def read_items(x_token: Annotated[list[str] | None, Header()] = None):
    return {"X-Token values": x_token}

此处形参 x_token 经过默认转换后对应 X-Token,且因注解为 list[str],重复值会被收集为列表。若客户端同时发送两条同名请求头:

X-Token: foo
X-Token: bar

接口返回的结果会是:

{
    "X-Token values": [
        "bar",
        "foo"
    ]
}

注意到列表中 bar 排在了 foo 前面,这与请求头的实际接收与解析顺序有关;作为调用方,不应依赖重复请求头的相对顺序。仓库配套测试 tests/test_tutorial/test_header_params/test_tutorial003.py 对上述行为做了逐项验证:不传时返回 None、传单个值时返回单元素列表、传两个值时返回两个元素的列表。

此外,你也可以用 list 表示法搭配可选语义(None 缺省),这样请求头完全缺失时返回 None,出现一次及以上时返回对应数量的列表,语义清晰且不抛错。

运行与验证

你可以把上述任一示例保存为本地文件并用 uvicorn 运行:

uvicorn main:app --reload

然后通过 curl 或直接在 http://127.0.0.1:8000/docs(Swagger UI)中测试请求头参数的效果。仓库中为每个示例都提供了对应的自动化测试,例如 tests/test_tutorial/test_header_params/test_tutorial001.py 会用 TestClient 发送 User-Agent 请求头,并断言返回体与 OpenAPI schema 中该参数以 "name": "User-Agent""in": "header" 的方式呈现。

总结

在 FastAPI 中声明请求头参数的完整套路与 QueryPathCookie 如出一辙,核心要点只有四条:

  1. fastapi 导入 Header
  2. 在路径操作函数形参上用 Header() 标记,并可用 Annotated 组合类型与默认值;
  3. 无需为形参名中的下划线烦恼——默认情况下 FastAPI 会自动将其转换为连字符以匹配标准 HTTP 请求头,需要严格匹配字面名称时可设 convert_underscores=False(但要注意代理层对下划线请求头的限制);
  4. 将类型注解声明为 list[...],即可接收同一请求头重复出现的多个值。

请求头参数本质上仍是 FastAPI"以类型注解驱动参数解析"设计哲学的一部分。想进一步了解请求头相关扩展能力,可继续阅读仓库中的查询参数(docs/en/docs/tutorial/query-params.md)、路径参数(docs/en/docs/tutorial/path-params.md)与 Cookie 参数(docs/en/docs/tutorial/cookie-params.md)等姊妹章节,理解它们如何共享同一套 Param 基类与校验体系。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388