Nginx 默认 access 日志记录重定向后的 URI,要记录原始请求地址需在重定向前捕获:推荐用 map 提前固化 $request_uri 为 $original_uri;也可在 location 内 return 前用 set 保存;或开启 rewrite_log 辅助调试。

Nginx 默认 access 日志记录的是最终处理完成时的 $uri 和 $request_uri,也就是重定向(如 return 301 或 rewrite ... permanent)执行后的地址,而不是用户最初发起请求的那个原始 URL。要记录跳转前的原始请求地址,关键在于在重定向发生前就捕获并保存原始值,再通过自定义日志变量输出。
以下是最实用、可落地的三种方法:
使用 $request_uri 配合 map 提前标记原始路径
$request_uri 天然包含完整原始请求(路径 + 查询参数),但它在 rewrite 或 return 后可能被覆盖或重置。稳妥做法是在请求进入第一阶段就用 map 提取并固化:
http {
# 在 http 块顶部定义,确保早于所有 server 块执行
map $request_uri $original_uri {
default $request_uri;
}
log_format redirect_log '原始URI:"$original_uri" → 目标URI:"$request_uri" 状态:$status';
server {
listen 80;
server_name example.com;
location /old/ {
return 301 https://example.com/new$request_uri;
}
access_log /var/log/nginx/redirect.log redirect_log;
}
}✅ 优势:不依赖 rewrite_log,不增加 debug 日志量,稳定可靠;$original_uri 在任何重定向指令前已确定。
在 return 或 rewrite 前用 set 显式保存
适用于单个 location 内需精确控制的场景(比如只对某类跳转记录原始地址):
location /legacy/ {
set $saved_original $request_uri; # 立即保存原始值
return 301 https://example.com/v2/$saved_original;
}
log_format save_log '原始:$saved_original | 当前:$request_uri | $status';
access_log /var/log/nginx/save.log save_log;⚠️ 注意:set 必须放在 return / rewrite 之前,且不能在 if 块中使用(Nginx 官方不推荐在 if 中用 set)。
启用 rewrite_log on 并配合 error 日志抓上下文
虽然不直接进 access 日志,但它是调试重定向链最直观的方式:
http {
rewrite_log on; # 开启后,notice 级别记录 rewrite 行为
error_log /var/log/nginx/error.log notice;
}重启后,错误日志中会出现类似:
*123456 "rewrite ^/a/(.*)$ /b/$1 permanent" matched *123456 "return 301 https://x.com/c$request_uri" executed
结合 grep -E "(rewrite|return|cycle)" /var/log/nginx/error.log 可清晰看到原始匹配与跳转目标的对应关系。
本质上,Nginx 没有内置“跳转前 URI”变量,必须靠主动捕获。用 map 固化 $request_uri 是生产环境最推荐的做法——它轻量、无副作用、兼容所有重定向类型(return、rewrite permanent、302 等),且不影响性能。


















