Nginx中rewrite在proxy_pass前执行,用于改写URI;proxy_pass不带路径时保留rewrite结果,带路径时自动前缀替换,可能绕过rewrite;break终止当前location处理,last触发重新匹配;推荐用map替代if实现动态代理,调试时用$log_uri或return验证。

在 Nginx 中,Rewrite 规则和反向代理(proxy_pass)常一起使用,但要注意执行顺序:Rewrite 在 proxy_pass 之前生效,所以通常用 rewrite 改写请求 URI,再由 proxy_pass 转发到后端。关键在于 URI 处理是否带路径、斜杠是否匹配,否则容易 404 或路径错乱。
rewrite 修改请求路径后再 proxy_pass
常见需求是把 /api/v1/xxx 重写为 /v1/xxx 再代理到后端服务:
- 用
rewrite指令改写 URI,注意末尾的break或last——break终止当前 location 的 rewrite 处理,last会重新匹配 location; -
proxy_pass后不带 URI(即结尾无路径),则转发时保留原始或 rewrite 后的完整 URI; - 如果
proxy_pass带 URI(如proxy_pass http://backend/v1/;),Nginx 会将匹配的 location 前缀替换为该 URI,此时 rewrite 可能被绕过,需谨慎。
示例:
location /api/ {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
}
访问 /api/user → rewrite 成 /user → 转发到 http://127.0.0.1:8000/user。
proxy_pass 直接带路径时 rewrite 的作用变小
当 proxy_pass 指定了目标路径(如 http://upstream/path/),Nginx 会自动做前缀替换,此时 rewrite 往往不需要,甚至可能干扰:
-
location /old/ { proxy_pass http://backend/new/; }:访问/old/a自动转为/new/a; - 若同时加
rewrite ^/old/(.*)$ /new/$1 break;,反而可能造成双重替换,导致路径错误; - 这种情况下,rewrite 更适合做条件判断(如根据参数跳转)或兼容旧 URL,而非路径标准化。
配合 if + rewrite 实现动态代理路由
虽然 if 在 location 中受限,但在简单判断下仍可结合 rewrite 控制流向:
- 比如根据请求头或参数决定代理目标:
-
if ($arg_env = "test") { rewrite ^(.*)$ $1 break; proxy_pass http://test-backend; }(注意:proxy_pass 不宜直接写在 if 内,推荐用 map 提前定义变量); - 更稳妥做法是用
map指令预设 upstream 名称,再在 proxy_pass 中引用变量。
调试技巧:加日志确认 URI 实际值
rewrite 和 proxy_pass 的行为容易误判,建议开启 access_log 或用 log_format 记录真实 URI:
- 在 log_format 中加入
$request_uri(原始)、$uri(rewrite 后未编码)、$request_filename(映射到文件系统路径); - 临时加
return 200 "URI: $uri\n";可快速验证 rewrite 效果; - 注意:rewrite 中的
$1是正则捕获,确保括号匹配且没有多余空格。


















