如何将FastAPI的request headers调整为可修改的可变对象?
问题原因
FastAPI 基于 Starlette 实现,默认提供的 request.headers 是 Starlette 封装的不可变 Headers 类实例,框架默认设计为禁止直接修改,避免请求链路中出现不可预期的状态变更,因此直接通过键赋值的方式修改会抛出 TypeError: 'Headers' object does not support item assignment 错误。
解决方案
根据使用场景可以选择两种不同的处理方案:
场景1:仅在当前逻辑中使用修改后的 headers,不需要传递给后续路由/依赖
直接将不可变的 Headers 对象转为普通 Python 字典操作即可,无需修改原始请求对象,性能损耗最低:
from fastapi import Request # 示例在中间件中操作,路由函数内操作逻辑一致 @app.middleware("http") async def process_headers(request: Request, call_next): # 转为可变字典 mutable_headers = dict(request.headers) # 修改请求头 mutable_headers["authorization"] = "XXXXXX" # 删除请求头,pop 第二个参数避免key不存在时报错 mutable_headers.pop("x-need-remove-header", None) # 后续当前逻辑直接使用 mutable_headers 即可 response = await call_next(request) return response
场景2:需要修改原始请求对象的 headers,传递给后续路由/依赖使用
如果需要让后续链路中所有拿到 request 对象的逻辑都能获取到修改后的 headers,需要重新构造 Request 对象,替换 scope 中的 headers 配置:
from fastapi import Request from starlette.datastructures import Headers @app.middleware("http") async def modify_request_headers(request: Request, call_next): # 先转字典完成自定义修改 mutable_headers = dict(request.headers) mutable_headers["authorization"] = "XXXXXX" mutable_headers.pop("x-need-remove-header", None) # 用修改后的字典构造新的 Headers 实例 new_headers = Headers(mutable_headers) # 构造新的 Request 对象,替换 headers 配置 request = Request( scope={**request.scope, "headers": new_headers.raw}, receive=request.receive, send=request.send ) # 后续所有链路拿到的 request 都携带修改后的 headers response = await call_next(request) return response
注意事项
- Starlette 的 Headers 类会自动将所有 header 键转为小写,操作时建议统一使用小写键,避免匹配失败
- 构造新 Request 时需基于原始 scope 生成新字典后再修改,不要直接修改原始 scope 对象,避免影响其他并行请求
- 如果不需要传递修改后的 headers 给后续链路,优先使用转字典的方案,性能更高
内容的提问来源于stack exchange,提问作者vee
相关产品推荐
相关产品推荐

