要记录重写后的url路径,需在rewrite后用set $final_uri $uri捕获,并在log_format中引用;$uri是重写后无查询参数的规范化路径,必须在同级location中rewrite之后立即设置,避免last导致失效。

默认情况下,Nginx 的 $request_uri 变量记录的是客户端原始请求的 URI(含查询参数),而重写(rewrite)后的最终目标路径并不会自动写入访问日志。要记录重写后的 URL 路径,需在重写完成后,用一个自定义变量捕获最终路径,并在 log_format 中引用它。
使用 set + rewrite 捕获最终路径
核心思路是:在所有重写规则执行完毕后,用 set 将 $uri(或 $request_uri,取决于是否需要保留查询参数)赋值给一个自定义变量(如 $final_uri)。注意 $uri 是重写后、未带查询参数的路径;$request_uri 始终是原始请求 URI,不能直接用——必须在重写完成后主动保存。
示例配置:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'final_path:"$final_uri"';
<p>server {
location /old/ {
rewrite ^/old/(.*)$ /new/$1 last;
set $final_uri $uri; # ✅ 在 rewrite 后立即设置
}</p><pre class="brush:php;toolbar:false;">location /api/v1/ {
rewrite ^/api/v1/(.*)$ /v2/$1 break;
set $final_uri $uri;
}
# 兜底:未匹配 rewrite 的请求,final_uri = 原始 uri
set $final_uri $uri;
access_log /var/log/nginx/access.log main;}
确保变量在重写后生效的关键点
-
变量赋值必须放在 rewrite 之后且同级作用域内:例如都在同一个
location块中,且set行在rewrite行下方(Nginx 按顺序执行) -
避免用
last跳出当前 location 导致 set 失效:如果用了last,Nginx 会重新匹配 location,之前 location 内的set不会继承。此时应在新匹配到的 location 中再次set $final_uri $uri -
用
$uri而非$request_uri:因为$uri是重写解析后的规范化路径(已解码、无查询串),更符合“最终目标路径”的语义
进阶:统一处理所有 location 的最终路径
若站点有大量重写规则,可在 server 级别初始化变量,并在每个 location 结尾显式赋值,或借助 map 指令预定义映射关系。但最稳妥通用的方式仍是:在每个可能触发重写的 location 块末尾,加一行 set $final_uri $uri。
补充说明:Nginx 不提供内置的“重写后 URI”只读变量,所以必须手动捕获。只要保证 set 发生在所有重写完成之后、日志写入之前,就能准确记录。











