上游请求头
forward_client_headers 用于点名调用方发来、需要由 AISIX 中继给上游的入站请求头。它在 AISIX 代理的四个面上是同一个字段、同一套语义,取值是一个请求头名称模式数组,默认为空。
需要配置它的场景,是上游需要某些只有调用方才能提供的信息:服务提供方的 Beta 功能标记、应用路由提示、链路关联请求头;或者当上游是按最终用户(而不是按网关)授权的内网服务时,调用方自己的凭证。
字段所在的位置取决于由哪个面访问上游:
| 字段 | 适用范围 |
|---|---|
provider_key.request.forward_client_headers | 使用该服务提供方密钥的标准协议端点(/v1/chat/completions、/v1/completions、/v1/messages、/v1/responses、/v1/realtime, 以及 embeddings、rerank、音频、图像、视频和 files/batches/fine-tuning 接口)。/v1/realtime 上该字段生效,但 default_headers 不生效,详见下文。 |
passthrough_route.forward_client_headers | 由该透传路由处理的请求。 |
mcp_server.forward_client_headers | 对该 MCP 服务器的工具调用,type: mcp 和 type: openapi 均适用。 |
a2a_agent.forward_client_headers | 对该 A2A Agent的调用——/a2a/<name> 上的每个 JSON-RPC 方法,以及 agent card 拉取,均适用。 |
两种管理路径都可以在这四个资源上配置该字段。加载声明式资源文件的网关支持本文的全部内容,AISIX Cloud Admin API 和控制台同样如此——包括精确点名凭证槽位的条目,而这正是按最终用户授权的内网上游所依赖的写法。
该字段在各处的行为一致——被模式点名的请求头就会到达上游——但各个面的默认行为并不相同,因此设置它的实际含义也不同:
- 在标准端点、MCP 和 A2A 上,AISIX 从头构建上游请求,不中继任何调用方请求头。此时该列表是白名单:它是调用方请求头到达上游的唯一途径。
- 在透传路由上,AISIX 默认中继调用方的请求头,只剥离一小部分。此时该列表是对剥离集合的覆盖:它只对路由本会删除的那些请求头有意义,其中包括网关刚刚用来认证调用方的那个凭证槽位。
服务提供方密钥上还有另一个与之无关的请求头设置:request.default_headers 添加由 AISIX 生成的请求头,其值可以引用当前请求。两者都位于服务提供方密钥上,因此引用该密钥的每个模型都会继承它们。
前置条件
开始前请准备:
- 上游服务提供方凭证和端点。示例会在服务提供方密钥上配置这些设置;该资源的其他字段参见服务提供方密钥。
- 对于 AISIX Cloud,需要环境、已关联网关和具有写入权限的 Admin Token。对于 On-Premises 部署,请按照 AISIX Cloud 快速入门操作。如需申请 Hybrid Cloud 访问权限,请联系 API7。
- 对于开源 AISIX 网关,需要一个加载声明式资源文件的网关。
配置上游请求头
请使用与你的部署方式对应的管理路径配置服务提供方密钥。两种路径下,这些设置的运行时行为相同。
AISIX Cloud
导出 AISIX Cloud 连接信息和上游凭证:
# AISIX_CP 是 Admin API 基础 URL;应包含 /api,且不含尾部斜杠
# 本地私有化部署快速入门使用 http://localhost:8080/api
export AISIX_CP="YOUR_AISIX_CLOUD_ADMIN_API_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
export UPSTREAM_API_KEY="YOUR_UPSTREAM_API_KEY"
创建一个注入网关上下文并转发获准客户端请求头的服务提供方密钥。这两项设置可以独立配置;下例展示它们如何共存于同一密钥:
curl -sS -X POST "$AISIX_CP/provider_keys" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "internal-vllm",
"provider": "byo",
"adapter": "openai",
"api_key": "'"${UPSTREAM_API_KEY}"'",
"api_base": "https://models.internal.example.com/v1",
"allowed_environments": ["'"${ENV_ID}"'"],
"request": {
"default_headers": {
"x-tenant-id": "${request.api_key.team_id}",
"x-audit-context": "key=${request.api_key.id};model=${model.name}",
"x-correlation-id": "${request.id}",
"x-upstream-tier": "premium"
},
"forward_client_headers": [
"anthropic-beta",
"x-routing-hint",
"x-trace-*"
]
}
}'
❶ 调用方 API Key 所属团队,可用于标识租户,以便上游进行配额或路由决策。
❷ 由字面文本、调用方 API Key 标识符和面向调用方的模型名称组合而成的值。
❸ 当前请求的关联 ID,与 AISIX 在 x-aisix-request-id 中发送并写入自身日志的值相同。
❹ 字面值,每个请求都会原样发送。
❺ 入站请求头名称和模式的允许列表。AISIX 在向上游发送请求前,仍会移除绝不转发的请求头。凭证或链路上下文请求头需要精确点名;这里的 x-trace-* 模式并不会匹配 traceparent。
响应中会包含服务提供方密钥 ID。如需稍后更改请求头设置,请保存该 ID:
export PK_ID="YOUR_PROVIDER_KEY_ID"
后续修改配置
PATCH /provider_keys/{id} 会整体替换 request 配置块,变更会影响引用该密钥的每个模型。请先读取当前配置块,然后在编辑后的请求中发送要保留的所有字段:
curl -sS "$AISIX_CP/provider_keys/$PK_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
| jq '.provider_key.request'
curl -sS -X PATCH "$AISIX_CP/provider_keys/$PK_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"request": {
"default_headers": {
"x-tenant-id": "${request.api_key.team_id}"
},
"forward_client_headers": ["anthropic-beta", "x-trace-*"]
}
}'
空的 "request": {} 会清除已存储的覆盖设置。目录服务提供方密钥会恢复为服务提供方的内置默认值;BYO 密钥清除后没有请求覆盖设置。省略 request 则会保留已存储的配置块。
在控制台中,相同配置块位于服务提供方密钥编辑表单的 Advanced wire-shape overrides 下,并会预填已存储值。
开源 AISIX 网关
将 request 配置块添加到 resources.yaml 中的服务提供方密钥条目。保留该条目已有的凭证字段,以及其他无关条目和集合。下例使用 UPSTREAM_API_KEY,该变量必须可供网关进程使用:
provider_keys:
- display_name: internal-vllm
provider: byo
adapter: openai
api_key: ${UPSTREAM_API_KEY}
api_base: https://models.internal.example.com/v1
request:
default_headers:
x-tenant-id: $${request.api_key.team_id}
x-audit-context: key=$${request.api_key.id};model=$${model.name}
x-correlation-id: $${request.id}
forward_client_headers:
- anthropic-beta
- x-trace-*
在资源文件中,未转义的每个 ${NAME} 都会在文件加载时从环境中替换。请将请求上下文引用中的美元符号转义为 $${...}。加载器会将 $$ 转换为字面 $,因此 $${request.id} 到达网关运行时会变成 ${request.id}。转义后的名称如果不在可用变量中,运行时不会解析,AISIX 会丢弃该请求头。
添加或更改该配置块后,请验证并重新加载完整资源文件。完整工作流参见重新加载资源文件,完整字段 目录参见资源文件参考。
请求上下文请求头值
当上游需要知道调用者身份时,使用 request.default_headers。内部模型服务可以据此应用租户配额、把成本归属到团队,或将自身访问日志与 AISIX 请求 ID 关联。这些请求头可以避免为每个租户准备单独的上游凭证。
请求头值可以是字面字符串、${...} 引用,也可以是字面文本与多个引用的组合。AISIX 会在认证调用方并选择模型后解析每个引用。
可用变量
| 变量 | 值 |
|---|---|
request.id | 当前请求的关联 ID。 |
request.api_key.id | 调用方 API Key 的标识符。 |
request.api_key.name | 调用方 API Key 的名称。 |
request.api_key.team_id | 调用方 API Key 所属团队。 |
request.api_key.user_id | 拥有调用方 API Key 的组织成员。 |
model.id | 解析后模型的标识符。 |
model.name | 解析后模型面向调用方的名称,而不是上游模型名称。 |
provider_key.id | 当前服务提供方密钥的标识符。 |
provider_key.name | 当前服务提供方密钥的 名称。 |
只有这些变量会在请求时解析。保存服务提供方密钥时,如果值引用了其他名称,AISIX Cloud Admin API 会拒绝该值,使拼写错误立即失败,而不是变成一个永远无法到达上游的请求头。资源文件另有一个加载时插值步骤,因此请求上下文引用需要按开源 AISIX 网关一节所述进行转义。
所有变量都不会暴露密钥。调用方 API Key、上游凭证和签名材料都不属于请求头值可以读取的请求上下文。
如果请求头引用的变量在某次请求中并非都有值,AISIX 会从该请求中删除整个请求头,而不是发送空值。如果调用方 API Key 不属于任何团队,上述示例的请求会包含 x-audit-context 和 x-correlation-id,但不会包含 x-tenant-id。空的 x-tenant-id 会让上游误以为租户是空字符串。
受保护的请求头名称
request.default_headers 不能设置那些任何配置都无法放到上游请求上的名称:host、逐跳请求头集合,以及网关自己的 x-aisix-* 命名空间。两种管理路径在这条边界上是一致的——保存服务提供方密钥时 AISIX Cloud 会拒绝这些名称,读取资源文件的网关则在分发时丢弃它们。它们就是 AISIX 绝不转发的调用方请求头中的第一组,无论请求头来自哪里,这一组都会约束 default_headers。那里的第二组只针对从调用方收到的请求头,因此对 default_headers 不构成任何限制。
凭证名称不在其中。在 default_headers 中点名 authorization、x-api-key 或其他凭证槽位,正是让“读取第二份静态凭证”的上游拿到该凭证的方式——前提是该服务提供方自身的凭证走的是另一个槽位。
这类条目做不到的,是顶替 AISIX 已经设置的请求头。默认请求头只会填充所选服务提供方桥接留空的槽位,绝不会替换上游凭证或 content-type。
转发客户端请求头
每个条目可以是精确的请求头名称,也可以是包含一个 * 通配符的名称。匹配不区分大小写,因此 X-Trace-* 和 x-trace-* 是同一个模式,都能匹配 x-trace-id。列表为空或不存在时(默认值),既不转发任何请求头,也不覆盖任何剥离行为。
调用方不能自行获得转发资格。该列表属于上游侧资源上的运维方配置;没有被任何条目点名的调用方请求头,其处理方式与未配置该字段时完全一致。
在标准端点、MCP 和 A2A 上,如果调用方多次发送同一个请求头,只有第一个值会被转发、其余丢弃,让上游收到一个格式良好的请求头,而不是一个网关从未解读过的列表。透传路由则按调用方发来的原样中继,包括重复项。
有一个请求头会让调用方为这条规则付出代价,而重复发送它并不是调用方自己的选择:cookie。AISIX 会终结入站的 HTTP/2,并且不做 cookie 重组(RFC 9113 第 8.2.3 节),因此如果 HTTP/2 调用方的客户端把 cookie 拆成多个请求头字段(这是 HPACK 的一种压缩手段,并非每个客户端都会这么做),只有第一个字段会被转发。同样的例外依然成立:透传路由会中继它收到的每一个 cookie 字段。
有些请求背后根本没有调用方——例如异步任务的后台轮询,或语义路由发起的向量检索。无论如何配置,这些请求都不转发任何内容,因为并不存在可供取值的入站请求。
/v1/realtime WebSocket 会像其他标准端点一样,转发其服务提供方密钥列表点名的请求头。有三点是这个面独有的:
- 除了任何面上都无法触及的名称之外,它还会拒绝自己拥有的五个握手槽位——
sec-websocket-accept、sec-websocket-extensions、sec-websocket-key、sec-websocket-protocol和sec-websocket-version。它们描述的是调用方向 AISIX 打开的那次握手,而不是 AISIX 向上游打开的那次。 - 任何模式都触及不到这五个,包括完整写出名称的模式:这个面会先检查自己的拒绝清单,再去查列表。其中最要紧的是
sec-websocket-protocol——浏览器流程会把调用方自己的 AISIX Key 作为一项放进那个列表里。 request.default_headers在这里不生效。服务提供方密钥request块的一半在这个面上生效,另一半不生效。
转发值如果不是 ASCII,会从握手中被丢弃,而不是让整个会话失败——因为这个面是以文本形式写出它到上游的握手的。其他每个面都会按字节原样转发同一个取值。
在路由、MCP 服务器或 A2A Agent 上配置
在透传路由、MCP 服务器和 A2A Agent 上,该字段位于顶层而不是 request 块内,模式写法完全相同。
通过 AISIX Cloud Admin API,把你希望它最终具备的完整列表 PATCH 上去。ROUTE_ID、SERVER_ID 和 AGENT_ID 是创建该路由、该服务器和该 Agent 时返回的 ID:
curl -sS -X PATCH "$AISIX_CP/environments/$ENV_ID/passthrough_routes/$ROUTE_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"forward_client_headers": ["authorization", "x-trace-*"]}'
curl -sS -X PATCH "$AISIX_CP/mcp_servers/$SERVER_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"forward_client_headers": ["authorization"]}'
curl -sS -X PATCH "$AISIX_CP/a2a_agents/$AGENT_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"forward_client_headers": ["authorization"]}'
PATCH 是整体替换已存储的列表,而不是追加。三个资源都可以用空数组清空;透传路由还额外接受 null,而 MCP 服务器和 A2A Agent 不接受。省略该字段时,已存储的列表保持不变。
在控制台中,同一设置是透传路由、MCP 服务器 和 A2A Agent 表单里 Advanced 下的 Forward client headers 输入框,每行填一个请求头名称或通配符。
在开源 AISIX 网关加载的资源文件中这样配置:
passthrough_routes:
- name: internal-copilot
path_prefix: /internal
target_url: https://models.internal.example.com
auth_mode: gateway_key
# 默认值 `inject` 需要配一个服务提供方密钥来注入。
credential_mode: forward_client
forward_client_headers:
- authorization
- x-trace-*
mcp_servers:
- name: runbooks
type: mcp
url: https://runbooks.internal/mcp
# 不配网关凭证:该服务器读取的就是调用方自己的凭证。
auth_type: none
forward_client_headers:
- authorization
a2a_agents:
- name: invoice-processor
url: https://agents.internal.example.com/a2a
# 该 Agent 按最终用户授权,读取的就是调用方自己的 Token。
auth_type: none
forward_client_headers:
- authorization
- x-trace-*
必须精确点名的请求头
通配符不会匹配到 AISIX 自己当作凭证消费的请求头,也不会匹配到 W3C 链路上下文请求头。转发这类请求头是一个明确的动作,完整写出名称才会转发它。
在所有面上都需要单独点名的是:
| 请求头 | 类别 |
|---|---|
authorization、proxy-authorization、x-api-key、api-key、x-goog-api-key、cookie | 凭证槽位 |
x-amz-security-token、x-amz-date、x-amz-content-sha256 | 凭证槽位(AWS SigV4 材料) |
traceparent、tracestate | W3C 链路上下文 |
这三个 x-amz-* 名称作为同一份调用方身份一起传递。x-amz-security-token 是一份有效的 AWS 会话凭证,另外两个则是签名所覆盖的时间戳与请求体哈希。任何通配符都触及不到它们,x-amz-* 也不例外。因此要把调用方的 AWS 凭证中继出去,必须把三个名称逐个完整写出来,并连同 authorization 一起点名——签名本身由该请求头承载,它同样需要单独写出名称。Bedrock 服务提供方密钥对同样这几个名称适用的是另一条规则——它会把它们丢弃,好让自己的签名器独占这些请求头。本页其余规则都把这三个名称当作凭证槽位对待,包括顶替行为在内。
透传路由还会加上它自己点名的两个槽位。AISIX 会消费掉这两个请求头,而共享清单无从知道某条路由为它们取了什么名字:
| 请求头 | 类别 |
|---|---|
路由的 auth_header_name | auth_mode: header_key 下承载网关凭证 |
路由的 identity_header | 路由负责记录并剥离的最终用户身份 |
完整写出其中任意一个才会转发它,通配符触及不到。否则,配置为 ["x-*"] 的路由就会把 AISIX 刚刚用来认证调用方的那个请求头中继出去,或者把路由承诺要剥离的那个身份取值中继出去。
写下 * 或 x-*,表达的是关于你自己那些请求头的意图。它不构成“把调用方凭证交给第三方服务提供方”的同意,也不构成“把调用方的链路嫁接到该服务提供方遥测中”的同意——若无上述限制,只要调用方碰巧发送了这些请求头,宽泛的通配符就会造成上述后果。完整写出请求头名称就是这份同意,而且只需要这一步:"forward_client_headers": ["authorization"] 会在每个面上转发调用方的 Authorization。
这条规则也让已有的宽泛模式保持其编写时的含义。配置为 ["x-*"] 的服务提供方密钥不会因为网关升级,就开始中继调用方的 x-api-key—— 在 /v1/* 上,那个请求头装的是调用方自己的 AISIX 网关 Key。
转发调用方凭证
点名一个凭证槽位,是让本就按最终用户授权的内网上游在 AISIX 接入之后继续这样工作的方式。调用方的值会占用该槽位,取代 AISIX 本会注入到那里的凭证:
- 在服务提供方密钥上,取代该密钥自身的凭证。
- 在 MCP 服务器上,取代
auth_type本会填入的凭证——bearer和oauth2填authorization;api_key填的是api_key_header指定的请求头,除非type: openapi的服务器另行覆盖,否则为x-api-key。 - 在 A2A Agent 上,取代
auth_type本会填入的凭证——bearer填authorization,api_key填x-api-key。 - 在透传路由上,取代注入的服务提供方凭证;同时也取代
gateway_key身份认证本会对authorization和x-api-key执行的剥离。
MCP 服务器的 api_key_header 只要不恰好是上述必须精确点名的请求头之一,通配符就能匹配到它。它的默认值 x-api-key 属于凭证槽位,因此需要单独点名;而 type: openapi 的服务器如果把该槽位改名——比如改成 x-mcp-token——它就有了一个会被 ["x-*"] 匹配到的名称,此时发送该请求头的调用方提供的就是自己的上游凭证。
无论哪种情况,该槽位都是单值的:AISIX 会替 换而不是追加,因此上游只会收到一份凭证,永远不需要在两份之间做选择。AISIX 仍会照常先认证调用方——该设置只改变上游看到的内容,绝不改变 AISIX 认定的调用者身份。
转发出去的是调用方放在该槽位里的任何内容——不一定是最终用户的身份 Token。在 /v1/*、/a2a/*、gateway_key 模式的透传路由,以及所有 MCP 客户端上,调用方的 Authorization 装的就是 AISIX 调用方 API Key 本身,因此点名 authorization 会把一份有效的网关凭证发往上游。只在你愿意把该取值托付给它的上游上点名该槽位。
上游也必须是能接受它的一方:校验 aud 声明的上游会拒绝签发给网关的 Token。不要在公共模型服务提供方上点名凭证槽位。
只有凭证槽位才会顶替 AISIX 已经设置的内容。AISIX 放在请求上的其他请求头,都是为了让这次交互能够成立——例如服务提供方的异步模式标记或 API 版本选择器——因此同名的转发请求头会被丢弃,而不是被允许破坏这次调用。
W3C 链路上下文
AISIX 将调用方的 traceparent 和 tracestate 读作遥测输入。一个有效的入站 traceparent 会让网关的 HTTP SERVER 跨度成为调用方跨度的子级。取值格式错误或存在多个 traceparent 时,AISIX 会启动新的本地链路,而不会拒绝请求。只有 traceparent 有效时,AISIX 才会保留 tracestate。AISIX 导出的跨度参见 OTLP 链路结构。
读取链路上下文与中继它是两回事。默认情况下,AISIX 不会在任何面上把调用方的链路请求头发往上游。在 forward_client_headers 中精确点名 traceparent 或 tracestate,才会连同它们一起中继——这适用于向同一套链路后端上报的内网上游,而不适用于第三方服务提供方。
AISIX 绝不转发的调用方请求头
有些请求头是任何模式都无法触及的。这类限制存在的原因是:转发它们会破坏这次交互本身,而不是改变请求来自谁,因此无论如何配置都会生效。
这些限制也仅适用于调用方提供的值。AISIX 仍会为其中一些名称发送自己的值:它为构建的请求体设置 content-type,并添加 x-aisix-request-id。
第一组在每个面上都适用:
| 请求头组 | 请求头 | 原因 |
|---|---|---|
| Host | host | 它决定请求最终到达哪台服务器。 |
| 逐跳 | connection、keep-alive、te、trailer、transfer-encoding、upgrade、proxy-authenticate | 这些字段描述的是调用方与 AISIX 之间的连接,而不是 AISIX 与上游之间的连接。 |
| 网关所有 | x-aisix-* | 这些是 AISIX 就自己处理过的请求做出的断言。转发调用方副本会让调用方得以在上游伪造它们,同时也会丢失断言本身。在 proxy.request_id.accept_headers 中列出的请求头(默认是 x-aisix-request-id)只在一点上例外:AISIX 会从中读取请求 ID,随后把读到的取值以自己的请求头发出,因此上游收到的该名称只有一个值。 |
标准端点、MCP 和 A2A 会重建出站消息,因此还会额外排除第二组:
| 请求头组 | 请求头 | 原因 |
|---|---|---|
| 请求体与内容协商 | content-type、content-length、content-encoding、accept、accept-encoding、expect | 它们描述的是 AISIX 会重新序列化的请求体和它会解析的响应形态,因此调用方的副本描述的是另一条消息。 |
| 仅响应 | set-cookie | 这是一个响应头,出现在请求中没有意义。 |
| 服务提供方传输格式 | anthropic-version | 它选择 Anthropic 形态的上游以何种传输格式作答,而 AISIX 随后要解析该格式。调用方的取值会破坏解析。 |
| 客户端 SDK | x-stainless-* | 调用方 SDK 描述自身的版本请求头。如果转发给同样使用这些请求头标识其 SDK 的服务提供方,会破坏调用。 |
各个面自己还会多排除一些:
- MCP 还绝不转发
mcp-session-id、mcp-protocol-version和last-event-id。它们标识的是调用方与 AISIX 之间的会话,而不是 AISIX 向上游打开的会话;上游 MCP 服务器会拒绝一个并非自己签发的会话 ID。 - A2A 还绝不转发
a2a-version。它是 AISIX 自己就该 Agent 的protocol_version所固定的线格式版本做出的声明;调用方的副本会覆盖 这个固定值——Agent 会以运维方并未配置的信封形态作答,或者干脆拒绝这次调用。 - 透传路由原样中继请求体,因此上面第二组对它不适用——
content-type会保留下来。它在第一组之外额外排除content-length,因为出站客户端会根据拿到的请求体自行推导长度,中继过去的取值是一个请求分帧缺陷。 /v1/realtime还绝不转发sec-websocket-accept、sec-websocket-extensions、sec-websocket-key、sec-websocket-protocol和sec-websocket-version。它们描述的是调用方向 AISIX 打开的那次握手,而不是 AISIX 向上游打开的那次;即使模式完整写出名称也触及不到它们。
还有一个服务提供方特有的例外:在 AWS Bedrock 服务提供方密钥上,AWS SigV4 会根据所签名的请求推导出 authorization、x-amz-date、x-amz-content-sha256、x-amz-security-token、x-amz-target 和 x-amzn-bedrock-accept,这些名称无论来自 forward_client_headers 还是 default_headers 都会被丢弃。在那里提供取值只会破坏签名,而不会认证任何人。
这种丢弃属于 Bedrock 自己的签名器,与必须精确点名是两条不同的规则。在其他任何上游上,这三个 x-amz-* 名称都可以送达,但前提是模式把它们逐个完整写出来。
优先级
同名请求头来自多个位置时,AISIX 按以下方式确定:
request.default_headers优先于由request.forward_client_headers转发的请求头——两者都是运维方配置,而静态的那个是更明确的意图表达——但凭证槽位除外。转发值从default_headers条目手里拿走凭证槽位,和从网关自己手里拿走一样。default_headers条目绝不会替换 AISIX 自行设置的请求头,包括上游凭证、content-type和x-aisix-request-id。- 转发的调用方请求头只有在名称属于凭证槽位时,才会替换 AISIX 自行设置的请求头。对于其他任何名称,AISIX 设置的取值保持不变。
- 在透传路由上,
forward_client_headers的优先级高于服务提供方密钥的strip_headers。被剥离的名称并不是从此禁行:在credential_mode: inject下,列表为["x-*"]的路由会把被剥离的x-请求头重新放回上游请求上——对普通请求头名称来说,一个通配符就够了。精确点名规则对凭证或链路上下文请求头、以及路由自己那两个槽位仍然成立;而 AISIX 绝不转发的调用方请求头无论写什么模式都进不来。
请求头在传输时始终是单值的:AISIX 会替换而不是追加,因此上游不会同时收到同名的运维方值和调用方值。
验证
导出调用方 API Key 和模型别名,确保其可以使用引用该服务提供方密钥的模型。然后发送请求,并包含允许列表中指定的请求头:
# AISIX_PROXY 是网关源站;请勿包含尾部斜杠或端点路径
# 本地快速入门使用 http://127.0.0.1:3000。
export AISIX_PROXY="YOUR_AISIX_GATEWAY_URL"
export AISIX_API_KEY="YOUR_CALLER_API_KEY"
export MODEL_ALIAS="YOUR_MODEL_ALIAS"
curl -sS -X POST "$AISIX_PROXY/v1/chat/completions" \
-H "Authorization: Bearer $AISIX_API_KEY" \
-H "Content-Type: application/json" \
-H "x-trace-id: trace-0001" \
-d '{
"model": "'"${MODEL_ALIAS}"'",
"messages": [{"role": "user", "content": "ping"}]
}'
在上游服务的访问日志或同类请求遥测数据中确认预期请求头。
如果将 api_base 指向请求检查服务,请记住 AISIX 会把服务提供方密钥凭证和请求体发送到该 api_base 指向的地址。请使用自己控制的端点、测试服务提供方密钥上的一次性凭证,以及不包含真实数据的提示词。
如果缺少预期请求头,请检查:
- 请求头名称已列在
forward_client_headers中,或与其中一个通配符条目匹配。 - 请求头不属于 AISIX 绝不转发的调用方请求头。
- 凭证或链路上下文请求头是精确点名的,而不是靠通配符条目匹配的。在透传路由上,路由自己的
auth_header_name和identity_header同理。 - 在
/v1/realtime上,该请求头不属于这个面拒绝的握手槽位,也不是default_headers条目——request块的那一半在这里并不生效。 - 对于含变量的
default_headers值,调用方 API Key 确实具有该属性。没有所属团队的 Key 会删除引用request.api_key.team_id的请求头。 - 在资源文件中,每个请求上下文引用都已转义为
$${...},以避开加载时的环境变量插值。
后续步骤
- 服务提供方密钥:了解服务提供方密钥的其他配置,包括兼容性覆盖。
- 资源文件参考:查看声明式字段目录。
- 透传路由、MCP 上游身份认证和 A2A 上游身份认证:该字段出现的另外三个面。