<p>Nginx 通过 $http_<em> 和 $senthttp 变量间接访问请求与响应 Header 字段,字段名自动转为小写加下划线;空值需用 map 指令设默认值;不支持解析嵌套 JSON 或含非法字符的 Header。</p>

Nginx 的 log_format 本身不支持直接从请求或响应 Header 中“提取”任意自定义字段(比如 X-Request-ID 或 User-ID),但它可以通过内置变量 $http_* 和 $sent_http_* 间接访问 Header 内容 —— 前提是字段名符合命名规范且已存在。
使用 $http_XXX 获取请求 Header 字段
Nginx 会自动将请求头(Request Headers)中带连字符(-)的字段,转换为下划线(_)并加前缀 $http_,形成可引用的变量:
-
X-Request-ID→$http_x_request_id -
User-Agent→$http_user_agent -
Content-Type→$http_content_type -
My-Custom-Header→$http_my_custom_header
注意:字段名不区分大小写,Nginx 统一转为小写 + 下划线。若 Header 不存在,该变量值为空字符串(不是 -),可在日志中体现为留空。
使用 $sent_http_XXX 获取响应 Header 字段
同理,Nginx 提供 $sent_http_* 变量用于记录响应头(Response Headers)—— 但仅限于已被 Nginx 设置或透传的响应头(如后端返回的 X-App-Version):
- 确保后端服务确实返回了该 Header(如
X-Trace-ID) - Nginx 默认不修改或过滤响应头,只要未被
proxy_hide_header等指令屏蔽,就能通过$sent_http_x_trace_id访问 - 该变量在日志中记录的是响应发出时的值,适用于调试后端行为
处理缺失/空值与默认值
直接使用 $http_x_request_id 在日志中可能留空,影响分析。可通过 map 指令提供默认值或做条件映射:
map $http_x_request_id $log_request_id {
"" "-"; # 空值转为 "-"
default $http_x_request_id;
}然后在 log_format 中引用 $log_request_id:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$log_request_id;'限制与注意事项
- Header 名必须由字母、数字、连字符组成;含非法字符(如点号
.、冒号:)无法映射 -
$http_*仅读取请求头,不支持解析嵌套结构(如 JSON 字符串中的字段) - 若需从 Header 解析子字段(例如从
X-User-Data: {"id":123}提取 id),Nginx 原生不支持,需借助 Lua(OpenResty)或前置服务预处理 - 变量名区分大小写:写成
$http_X_Request_ID无效,必须全小写下划线形式


















