nginx access_log 不直接提供完整url,但可用 $request 变量原样记录请求行(如 get /path?a=1&b=2 http/1.1),推荐首选;若需拼接 https://host/path?query,须谨慎组合 $real_scheme、$host 与 $request_uri,并校验代理头;提取特定参数宜用 $arg_xxx 变量。

Nginx 的 access_log 本身不直接提供“完整 URL”(如 https://example.com/path?a=1&b=2)这一变量,但可以通过组合内置变量手动拼接实现,关键在于明确需求场景、选对变量、注意安全性与可靠性。
直接记录含参数的原始请求行(推荐首选)
最稳妥、兼容性最强的方式是使用 $request 变量——它天然包含方法、带 query string 的 URI 和协议版本,例如:
GET /api/v1/user?id=123&name=test%20user HTTP/1.1
配置示例(在 http 块中):
log_format full_request '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'args="$args"';
access_log /var/log/nginx/access.log full_request;
- ✅
$request原样保留 URL 编码(如%20),无需额外 decode - ✅ 不依赖
$host或$scheme,避免代理头伪造风险 - ✅ 所有 Nginx 版本均支持,零额外模块
拼接可访问的完整 URL(需谨慎使用)
若确实需要形如 https://example.com/api?x=1 的完整地址,需手动组合:
# 判断协议(优先信任 X-Forwarded-Proto,fallback 到 $scheme)
map $http_x_forwarded_proto $real_scheme {
default $scheme;
http http;
https https;
}
log_format full_url '$remote_addr - $remote_user [$time_local] '
'"$real_scheme://$host$request_uri" '
'$status $body_bytes_sent';
access_log /var/log/nginx/access.log full_url;
⚠️ 注意事项:
-
$host来自请求头Host字段,可能被客户端篡改 → 生产环境建议配合underscores_in_headers on;和白名单校验,或改用$server_name - 若服务部署在反向代理后(如 CDN、LB),必须确保
X-Forwarded-Proto和Host头可信,否则拼出的 URL 可能不可靠 -
$request_uri包含原始 query string,且未解码;若需解码后内容,Nginx 原生不支持,需后续日志分析阶段处理
提取特定参数做结构化记录(适合审计与过滤)
当只关注少数关键参数时,用 $arg_xxx 更清晰高效:
log_format api_audit '$remote_addr [$time_local] '
'path="$uri" '
'id="$arg_id" '
'token="$arg_token" '
'source="$arg_utm_source" '
'status=$status';
access_log /var/log/nginx/api_audit.log api_audit;
- ✅ 空参数自动记为空字符串,便于 grep 或 ELK 过滤
- ✅ 变量名规则:
?api-key=abc→$arg_api_key(短横线转下划线,全小写) - ✅ 不受
$args编码影响,提取的是解码后的值(Nginx 内部已处理)
不复杂但容易忽略。











