nginx需显式定义日志格式并使用$http_*变量记录指定请求头,或借助headers-more-nginx-module模块捕获全部原始头;前者推荐用于生产环境,后者仅适用于临时调试或审计。

要让 Nginx 的 access_log 记录完整的请求头,不能靠默认配置,必须显式定义日志格式并引入对应变量。Nginx 本身不提供“一键记录所有请求头”的内置变量,但可通过两种方式实现:一种是按需映射关键头(推荐、稳定),另一种是借助第三方模块捕获全部原始头(适合审计,但有代价)。
按需记录指定请求头(无需额外模块)
这是最常用、兼容性最好、生产环境首选的方式。核心是用 $http_* 变量引用具体请求头,变量名规则为:头名称转小写,短横线(-)替换为下划线(_)。
- 在
http块中定义日志格式,例如:
log_format full_headers '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent" '
"$http_x_request_id" "$http_trace_id" "$http_content_type" "$http_authorization"';
- 在
server或location块中启用:
access_log /var/log/nginx/access.log full_headers;
- 若客户端未发送某头(如
X-Request-ID),对应字段为空字符串,不会报错 - 常见映射示例:
X-Forwarded-For→$http_x_forwarded_forX-B3-Traceid→$http_x_b3_traceidContent-Type→$http_content_type
记录全部原始请求头(需 headers-more-nginx-module)
如果必须保留所有请求头(包括动态添加或未知名称的头),需编译安装 headers-more-nginx-module 模块,并使用其 more_set_input_headers 指令聚合头信息。
- 先启用模块后,在配置中加入:
more_set_input_headers 'All-Request-Headers: $http_headers';
log_format all_headers '[$time_local] $remote_addr "$request" $status "
$sent_http_content_type" "Input-Headers: $more_input_headers_all_request_headers"';
- 该方式输出类似:
"Input-Headers: X-Forwarded-For: 1.2.3.4, User-Agent: curl/7.68.0" - 优点:不遗漏任何头;缺点:日志体积大、结构松散、难以直接解析、增加磁盘与 I/O 压力
- 仅建议用于临时调试或安全审计,非长期线上标配
注意事项与避坑点
无论采用哪种方式,都要注意几个关键细节:
-
$http_*变量只读取请求头,不包含响应头;响应头要用$sent_http_*(如$sent_http_content_type) - 请求头名称区分大小写,但 Nginx 内部统一转为小写处理,所以
$http_X_Request_ID无效,必须写$http_x_request_id - 含敏感信息的头(如
Authorization、Cookie)建议脱敏后再记录,避免日志泄露凭据 - 高并发场景下,记录过多字段或启用全量头会显著增大日志体积,应结合
buffer=32k或gzip=6缓冲与压缩











