必须满足读取与缓存条件才能使$request_body非空:设置client_max_body_size、client_body_buffer_size和client_body_in_single_buffer on,限定location路径启用独立log_format,结合Content-Type过滤、base64编码及敏感字段脱敏,避免全站日志膨胀与安全风险。

要在 Nginx 日志中精准记录客户端请求体($request_body)的完整内容,不能只靠简单开启变量——它默认为空,必须满足明确的读取与缓存条件,并配合路径隔离、大小控制和安全处理。核心是“让 Nginx 真正拿到 body 并稳定暴露给日志”。
确保 $request_body 可用的关键配置
该变量仅在 Nginx 已完整读取并暂存请求体后才非空。需同时满足:
- 设置
client_max_body_size(如1m),避免因超限直接拒收 - 设置足够大的
client_body_buffer_size(如128k),使常见 body 能驻留内存 - 启用
client_body_in_single_buffer on,防止 body 被拆分导致变量为空 - 若走代理(如
proxy_pass),必须保持proxy_buffering on(默认即开启) - 禁用文件落盘:确保
client_body_in_file_only off(默认值),否则$request_body为空字符串
按路径精准启用,避免全站日志膨胀
不要在 http 或 server 块全局启用,而是限定到具体接口路径:
- 用
location = /api/v1/secure精确匹配,或location ~ ^/api/v1/secure支持带参路径 - 在该
location内定义独立log_format,例如:log_format secure_log '$remote_addr [$time_local] "$request" $status "$request_body"'; - 绑定专属日志文件:
access_log /var/log/nginx/secure-body.log secure_log;
处理大 body 和边界情况
当请求体超出缓冲区时,$request_body 会变为空。此时需结合其他手段:
- 检查
$request_length—— 它始终准确反映总请求字节数,可用于告警或过滤异常大包 - 若必须捕获超大 body,需启用
client_body_temp_path并配合 Lua(OpenResty)读取临时文件,但生产环境慎用 - 对
GET、HEAD等无 body 方法,$request_body恒为空,建议在日志格式中加条件判断或直接过滤 - 注意
Content-Type,可加if ($content_type ~ "application/json|application/x-www-form-urlencoded") { ... }提前拦截无关类型
安全与脱敏不可省略
明文记录请求体极易泄露敏感信息:
- 避免记录
Authorization、Cookie、密码字段等,可用map指令做关键词替换 - 日志文件权限设为
600,目录禁止 web 可读 - 考虑用
log_subrequest on控制子请求是否记 body,防止内部重定向重复记录 - 上线前务必压测:单次大 body 请求可能使日志体积激增数倍,影响磁盘与 I/O











