$sent_http_location 是 nginx 记录响应头 location 值的内置变量,仅在返回 301/302 等重定向状态码时非空,精确捕获本次响应声明的跳转目标 uri(第一跳终点),不追踪后续跳转。

$sent_http_location 是 Nginx 日志中记录响应头 Location 字段值的内置变量,仅在返回 301、302 等重定向状态码时有实际内容。它不“追踪路径”,而是**精确捕获本次响应所声明的跳转目标 URI**——即重定向的“第一跳终点”,而非最终落地页(除非是单次重定向)。
确认 $sent_http_location 是否生效
该变量只在响应头中真实存在 Location: 时才非空。常见失效场景:
- 后端应用(如 PHP、Node.js)自行写入
Location头但未设置状态码为 3xx → Nginx 不认为这是重定向,$sent_http_location 为空 - Nginx 配置了
return 301 ...或rewrite ... redirect,但被后续proxy_pass或try_files覆盖或拦截 → 实际响应不是重定向,变量无值 - 使用了
add_header Location ...→ 此操作不会触发 $sent_http_location 赋值,它只捕获 Nginx 自身生成或透传的原始 Location 响应头
在日志格式中正确引用并验证
在 http 或 server 块中定义日志格式,显式包含该变量:
注意:
- $sent_http_location 是 Nginx 发送给客户端的 Location 值(已做 URI 编码,如空格变 %20)
- $upstream_http_location 是上游服务返回的原始 Location 头(若用 proxy_pass),可用于比对是否被 Nginx 改写
- 启用该日志后,仅当访问触发 301 响应时,日志行中才会出现非空的 "..." 内容
区分“重定向终点”与“最终落卡页”
301 是 HTTP 协议级指令,浏览器收到后会自动发起新请求。Nginx 日志中的 $sent_http_location 只反映这一次响应告诉客户端去哪,不保证客户端真能到达、也不记录后续跳转。例如:
-
GET /old → 301 Location: /new→ 日志记/old → "/new" - 若
/new又被另一台服务器 301 到https://example.com/final→ 这一跳不会出现在当前 Nginx 日志里 - 要完整链路,需在每层反向代理或源站都开启含
$sent_http_location的日志,并关联请求 ID(如通过$request_id)
安全重定向路径审计建议
利用该变量做安全分析时,重点检查值是否符合预期:
- 是否为绝对 URL(含协议+域名)?避免开放重定向漏洞(如
Location: $arg_url未校验) - 是否指向可信域名?可用 logrotate + awk/grep 快速统计异常 host:
awk -F'"' '/→ "[^"]+"/ {split($2,a,"/"); print a[3]}' access.log | sort | uniq -c | sort -nr - 是否含非法编码或双斜杠(
//)、空字节等?这些可能是绕过检测的痕迹











