nginx 1.13.10+ 支持通过 $senttrailer* 变量捕获 http/2 trailer 元数据,但需后端在 trailer 响应头中显式声明字段名,并启用 http/2 协议;变量仅在响应阶段有效,用于日志、add_header 或 proxy_set_header。

在 HTTP/2 环境中,后端可通过 trailer headers(末尾元数据)在响应体传输完成后发送额外的元数据,例如处理耗时、签名、校验摘要等。Nginx 1.13.10+ 原生支持通过 $sent_trailer_* 变量捕获这些 trailer 字段,但需满足特定条件才能生效。
确保后端正确发送 Trailer 和实际 trailer 字段
HTTP/2 trailer 要求显式声明哪些字段将作为 trailer 发送,且必须在响应头中包含 Trailer: 头。例如:
Trailer: X-Process-Time, X-Signature<br> Content-Type: application/json<br> ...(响应体)<br> X-Process-Time: 142ms<br> X-Signature: sha256=abc123
若后端未在 Trailer 头中列出字段名,Nginx 不会将其纳入 $sent_trailer_* 变量,即使实际发送了该 header。
启用 Nginx 对 trailer 的解析与变量捕获
Nginx 默认不解析或暴露 trailer 字段。需在配置中显式启用:
- 使用
http2_max_requests或keepalive本身不影响 trailer 捕获,关键在于开启http2并确保使用 HTTP/2 协议通信 - 在
location或server块中添加:http2_push_preload off; # 非必需,但避免干扰 - 确认 Nginx 编译时启用了
--with-http_v2_module(主流发行版默认包含) -
$sent_trailer_x_process_time和$sent_trailer_x_signature将自动可用——注意:变量名转为小写、连字符转下划线,且前缀为sent_trailer_
在日志、响应头或代理中使用 $sent_trailer_* 变量
这些变量仅在响应阶段(即 log_format、add_header、proxy_set_header 等指令的响应上下文)中有效:
-
记录到 access log:
log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$sent_trailer_x_process_time" "$sent_trailer_x_signature"'; -
透传到客户端:
add_header X-Upstream-Process-Time $sent_trailer_x_process_time; -
转发给下一级服务:
proxy_set_header X-Backend-Signature $sent_trailer_x_signature;
⚠️ 注意:$sent_trailer_* 在请求阶段(如 if、rewrite)不可用;也不可用于条件判断(Nginx 变量在响应头生成后才被赋值)。
常见问题与验证方法
-
变量始终为空? 检查后端是否真正在 trailer 区域发送了该字段,并确认
Trailer:响应头已声明对应名称 -
HTTP/1.1 下无效? 是的,
$sent_trailer_*仅在 HTTP/2 连接中由 ngx_http_v2_module 提供,HTTP/1.x 不支持 trailer 元数据语义 -
如何调试? 用
curl -v --http2 https://example.com/endpoint观察响应末尾是否有 trailer 行;也可在后端日志中打印原始 trailer map
不复杂但容易忽略:trailer 不是“任意附加响应头”,而是 HTTP/2 协议定义的独立元数据区,Nginx 的变量机制严格遵循这一规范。











