上游请求头
在 /v1/chat/completions、/v1/messages 和 /v1/responses 等标准协议端点上,AISIX 会从头构建上游请求。它选择上游凭证、重写模型名称,并且只发送服务提供方协议要求的请求头。调用方发送的请求头不会转发,因此调用方不能使用自己的凭证或 Trace 上下文访问上游服务提供方。
当上游需要更多上下文时,可以通过两个服务提供方密钥设置扩展默认行为:
request.default_headers添加由 AISIX 生成的请求头,其值可以引用当前请求,例如调用方 API Key 所属团队。request.forward_client_headers将指定的入站客户端请求头(例如anthropic-beta或 Trace 请求头)转发到上游。
这两项设置都位于服务提供方密钥上,因此引用该密钥的每个模型都会继承它们。
本指南的主要示例使用 AISIX Cloud。对于开源 AISIX 网关,请在 resources.yaml 的 provider_keys 下使用相同字段。
前置条件
开始前请准备:
- 上游服务提供方凭证和端点。示例会围绕它们创建服务提供方密钥;该资源的其他字段参见服务提供方密钥。
- 对于 AISIX Cloud,需要环境、已关联网关和具有写入权限的 Admin Token。对于 On-Premises 部署,请按照 AISIX Cloud 快速入门操作。如需申请 Hybrid Cloud 访问权限,请联系 API7。
- 对于开源 AISIX 网关,需要一个加载声明式资源文件的网关。
导出 AISIX Cloud 连接信息和示例使用的值:
# AISIX_CP 是 Admin API 基础 URL;请包含 /api,且不要以斜杠结尾。
# 本地 On-Premises 快速入门使用 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"
# AISIX_PROXY 是网关源地址;请不要包含末尾斜杠和端点路径。
# 本地快速入门使用 http://127.0.0.1:3000。
export AISIX_PROXY="YOUR_AISIX_GATEWAY_ORIGIN"
# 第一个示例创建密钥后设置,供更新示例使用。
export PK_ID="YOUR_PROVIDER_KEY_ID"
# 允许访问引用该服务提供方密钥的模型的调用方 API Key,
# 以及该模型的别名——用于文末的验证请求。
export AISIX_API_KEY="YOUR_CALLER_API_KEY"
export MODEL_ALIAS="YOUR_MODEL_ALIAS"
注入请求上下文请求头
当上游需要知道调用者身份时,使用 request.default_headers。内部模型服务可以据此应用租户配额、把成本归属到团队,或将自身访问日志与 AISIX 请求 ID 关联,而且无需为每个租户准备单独的上游凭证。
请求头值可以是字面字符串、${...} 引用,也可以是字面文本与多个引用的组合。AISIX 会在认证调用方并选择模型后,按请求解析其中的每个引用:
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"
}
}
}'
❶ 调用方 API Key 所属团队,可作为上游配额或路由决策的租户标识符。
❷ 由字面文本、调用方 API Key 标识符和面向调用方的模型名称组合而成的值。
❸ 当前请求的关联 ID,与 AISIX 在 x-aisix-request-id 中发送并写入自身日志的值相同。
❹ 字面值,每个请求都会原样发送。
可用变量
| 变量 | 值 |
|---|---|
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 会拒绝该值,使拼写错误立即失败,而不是变成一个永远无法到达上游的请求头。资源文件另有一个加载时插值步骤,因此请求上下文引用需要按在资源文件中配置所述进行转义。
所有变量都不会暴露密钥。调用方 API Key、上游凭证和签名材料都不属于请求头值可以读取的请求上下文。
如果请求头引用的变量在某次请求中并非都有值,AISIX 会从该请求中删除整个请求头,而不是发送空值。如果调用方 API Key 不属于任何团队,上述示例的请求会包含 x-audit-context 和 x-correlation-id,但不会包含 x-tenant-id。空的 x-tenant-id 会让上游误以为租户是空字符串。
受保护的请求头名称
request.default_headers 不能设置 authorization、x-api-key、x-goog-api-key、api-key、x-amz-security-token、x-amz-date、x-amz-content-sha256、proxy-authorization、cookie 和 host。保存服务提供方密钥时,AISIX Cloud 会拒绝这些名称;即使它们进入了运行时配置,网关也会将其丢弃。
默认请求头同样不能替换所选服务提供方桥接已经设置的请求头,例如上游凭证、content-type 或 x-aisix-request-id。AISIX 绝不转发的调用方请求头中更宽泛的传输和命名空间限制针对的是从调用方收到的请求头,并不是对 default_headers 的全面限制。
转发客户端请求头
当调用方需要通过 AISIX 向服务提供方传递请求头时,使用 request.forward_client_headers。常见场景包括 Anthropic Beta 功能标记、分布式追踪请求头,以及内部模型平台读取的路由提示。
列出需要转发的请求头。每个条目可以是精确名称,也可以包含一个 * 通配符;匹配不区分大小写。两个配置块可以同时存在于同一服务提供方密钥上,下面分开展示只是为了让示例更清晰:
curl -sS -X POST "$AISIX_CP/provider_keys" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "internal-vllm-forwarding",
"provider": "byo",
"adapter": "openai",
"api_key": "'"${UPSTREAM_API_KEY}"'",
"api_base": "https://models.internal.example.com/v1",
"allowed_environments": ["'"${ENV_ID}"'"],
"request": {
"forward_client_headers": [
"anthropic-beta",
"traceparent",
"x-trace-*"
]
}
}'
❶ 精确名称。调用方发送 anthropic-beta 时,该请求头会到达服务提供方;未发送时则不会产生任何变化。
❷ W3C Trace Context 请求头,使 Trace 可以继续进入上游,而不是终止于 AISIX。
❸ 通配符条目,会匹配 x-trace-id、x-trace-parent 以及具有该前缀的其他名称。使用 x-* 可以转发所有 x- 请求头,但 AISIX 绝不转发的调用方请求头除外,任何模式都无法匹配这些请求头。
列表为空或不存在时(默认值),不会转发任何请求头。
调用方不能自行获得转发资格:该列表属于服务提供方密钥配置,没有被任何条目点名的调用方请求头仍会像以前一样被删除。
后续修改配置
在 AISIX Cloud 中,PATCH /provider_keys/{id} 接受相同的 request 配置块,变更会影响引用该密钥的每个模型。
该配置块会被整体替换,因此请发送需要保留的所有字段,而不只是发生变化的字段。先读取当前配置块——GET /provider_keys/{id} 会返回该值——然后提交编辑后的版本:
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": {} 会清除该配置块,让密钥恢复为其服务提供方的内置默认值。完全省略该字段则会保留已存储配置块。
控制台中,相同配置块位于服务提供方密钥编辑表单的 Advanced wire-shape overrides 下,并会预填已存储值。
AISIX 绝不转发的调用方请求头
无论如何配置,AISIX 都不会采用调用方发送的某些请求头。即使 forward_client_headers 中宽泛的模式本可以匹配到它们,网关也会在运行时将其过滤掉。
该限制针对调用方发送的副本。AISIX 仍会为其中一些名称发送自己的值,例如使用服务提供方密钥凭证进行身份认证、为构建的请求体设置 content-type,并添加 x-aisix-request-id。该请求 ID 可能是调用方提供的,但 AISIX 是以自己的请求头发出它,而不是转发调用方的副本,因此线路上该取值是唯一的。
| 请求头组 | 请求头 | 原因 |
|---|---|---|
| 身份认证 | authorization、x-api-key、api-key、x-goog-api-key、x-amz-date、x-amz-security-token、x-amz-content-sha256、proxy-authorization | AISIX 使用服务提供方密钥自身的凭证向上游认证。转发调用方凭证会将其泄露给第三方。 |
| 会话与路由 | cookie、set-cookie、host | 防止会话材料进入上游流量,并阻止通过 Host 重定向上游请求。 |
| 传输与代理 | connection、keep-alive、transfer-encoding、content-length、content-type、content-encoding、accept、accept-encoding、te、trailer、upgrade、expect、proxy-authenticate | 这些字段描述调用方连接、AISIX 将要重写的请求体,或中间代理,而不是 AISIX 发出的上游请求。 |
| 网关所有 | x-aisix-* | 这些请求头由 AISIX 自行设置,绝不会转发调用方副本。在 proxy.request_id.accept_headers 中列出的请求头(默认是 x-aisix-request-id)只在一点上例外:AISIX 会从中读取请求 ID。该请求头本身同样不会被转发——网关把读到的取值以自己的 x-aisix-request-id 发出,因此上游收到的该名称只有一个值。 |
| 客户端 SDK | x-stainless-* | 调用方 SDK 发送的自身版本请求头。如果转发给同样使用这些请求头标识其 SDK 的服务提供方,会破坏调用。 |
如果请求确实需要保留原始请求头,请改用透传路由。路由会按原样转发请求,只删除其凭证模式对应的剥离请求头;同时会放弃标准端点提供的协议转换、统一遥测和跨服务提供方功能。
哪些凭证可以过网关是路由的显式选择,绝不是剥离列表的副作用。inject 路由应用服务提供方密钥的 strip_headers 列表,并在注入服务提供方凭证前恒剥离 authorization 和 x-api-key,因此上游绝不会收到两份凭证。forward_client 路由把调用方自己的凭证请求头逐字中继,只剥离网关的旁路请求头。仅当上游本就是调用方凭证的归属方时才使用 forward_client。
优先级
同名请求头来自多个位置时,按以下顺序确定优先级:
- AISIX 所有的请求头,例如上游凭证、
content-type和x-aisix-request-id。 request.default_headers。- 由
request.forward_client_headers转发的请求头。
请求头在传输时是单值;AISIX 会替换而不是追加,因此上游不会同时收到同名的运维方值和调用方值。
在资源文件中配置
开源 AISIX 网关在资源文件中支持相同字段:
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}。转义后的名称如果不在可用变量中,运行时不会解析,网关会丢弃该请求头。
验证
通过引用该服务提供方密钥的模型发送请求,并包含白名单中指定的请求头:
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 绝不转发的调用方请求头。
- 对于含变量的
default_headers值,调用方 API Key 确实具有该属性。没有所属团队的 Key 会删除引用request.api_key.team_id的请求头。 - 在资源文件中,每个请求上下文引用都已转义为
$${...},以避开加载时的环境变量插值。