应使用 $request_uri 变量记录完整原始请求路径,因其保留客户端发送的原始 URI(含未解码的查询参数),不受重写影响;需在 log_format 中用双引号包裹,避免日志截断。
要在 Nginx 中通过 log_format 完整记录包含查询参数的原始请求路径,关键在于使用 $request_uri 变量 —— 它保留客户端发起的原始 URI(含协议解码前的完整路径和参数),不经过重写或标准化处理。
$request_uri 是 Nginx 内置变量,直接映射客户端发送的原始请求行中的 URI 部分(例如 GET /search?q=nginx%20log&sort=desc HTTP/1.1 中的 /search?q=nginx%20log&sort=desc)。它:
%20 不会转为空格)?... 及之后内容)rewrite、try_files 等指令影响,始终反映初始请求$uri(解码后路径,不含参数)和 $args(仅参数部分)有本质区别在 http 块中定义日志格式,将 $request_uri 直接加入字段列表:
log_format detailed '$remote_addr - $remote_user [$time_local] ' '"$request_method $request_uri $server_protocol" ' '$status $body_bytes_sent "$http_referer" "$http_user_agent"';
注意:$request_uri 必须用双引号包裹(防止空格和特殊字符截断日志),且无需额外转义 —— Nginx 会自动处理。
在 server 或 location 块中启用该格式:
access_log /var/log/nginx/access.log detailed;
发起测试请求,例如:
curl "http://localhost:8080/api/v1/users?name=张%20三&role=admin"
对应日志行中 $request_uri 部分会如实记录为:
$uri?$args 拼接 —— $uri 已解码,$args 是解码后的参数,拼接后丢失原始编码,且可能因空 $args 导致多余 ?
merge_slashes off,$request_uri 仍保持原始斜杠形式(如 //path),符合真实请求buffer 或 flush 参数,不影响 $request_uri 内容的准确性