$sent_http_location 仅记录实际发出的3xx响应中的原始location头值,对200或rewrite last无效;需结合$status、$upstream_http_location等字段分析重定向链路。

直接用 $sent_http_location 记录 301 重定向的目标 URL 是可行的,但它只在响应头中实际包含 Location 字段时才有值——也就是说,仅对返回状态码为 3xx(尤其是 301/302)的请求生效;对正常 200 响应或内部重定向(如 rewrite ... last)为空字符串。
确认 $sent_http_location 的触发条件
该变量是 Nginx 在发送响应头后捕获的 Location 头原始值,属于“已发出”的响应头,不是内部变量。因此:
- 它不会记录
return 301 /new-path中的路径,除非该指令最终生成了带Location: https://example.com/new-path的响应 - 它不反映
proxy_redirect或sub_filter修改后的 Location,而是上游真实返回或 Nginx 自己设置的原始值 - 如果后端返回 301 但没带
Location头(非法),该变量为空,日志中会显示短横线-
在 access_log 中正确配置字段
在 log_format 中显式引用该变量,并确保日志格式能清晰区分重定向行为:
log_format redirect_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$sent_http_location"';
然后在 server 或 location 块中启用:
access_log /var/log/nginx/redirect.log redirect_log;
注意:该变量在日志中只对 301/302 等响应有效,其他状态码下显示为空(即 "" 或 -),可结合 $status 字段一起分析。
排除常见干扰项
避免误判重定向终点,需注意以下几点:
-
相对路径问题:若后端返回
Location: /foo,Nginx 不会自动补全 scheme/host;日志中记录的就是/foo,需结合$scheme、$host和$request_uri手动还原完整跳转地址 -
多次跳转链路:Nginx 默认只记录本次响应的
Location,不追溯上游重定向链。如 A → B → C,Nginx 作为中间代理只记 B 返回的Location(即 C 地址),前提是开启proxy_redirect off或未被覆盖 -
内部 rewrite 干扰:使用
rewrite ^/old /new permanent;时,Nginx 自动添加Location响应头,此时$sent_http_location可捕获重定向目标(含协议和 host);但若用rewrite ... last;则无 301,该变量为空
辅助定位“落卡”终点的实用技巧
单靠 $sent_http_location 有时不足以判断用户最终到达哪一页,建议组合使用:
- 加
$upstream_http_location:当 Nginx 作为反向代理时,它记录上游响应的原始Location头,可用于对比是否被proxy_redirect修改过 - 加
$request_time和$upstream_response_time:快速识别是否因上游反复重定向导致延迟异常 - 用 map 构建标记字段:
map $sent_http_location $is_redirect {<br> ~^https?:// 1;<br> default 0;<br>}
再写入日志:'"$is_redirect" "$sent_http_location"',便于后续用 awk/grep 过滤真重定向
不复杂但容易忽略。关键是理解这个变量只反映“这一跳”发出去的 Location,而不是整个跳转链的终点;要精准追踪落点,得把它和请求上下文、代理行为、上游响应一起看。











