Nginx location 中 rewrite 执行于匹配后、处理前,break 阻止重匹配,last 触发新 location 匹配,redirect/permanent 立即返回跳转,需避循环、斜杠不一致及 proxy_pass 后写 rewrite 等错误。

Nginx 的 rewrite 规则在 location 块中编写时,关键在于理解匹配顺序、作用域和 flag 的行为。写错位置或 flag 会导致重定向循环、规则不生效或意外跳转。
location 中 rewrite 的执行时机与优先级
rewrite 指令在 location 块内属于“重写阶段”,它在 location 匹配完成后、实际处理请求前执行。但要注意:
- 如果
location是前缀匹配(如location /api/),且内部有rewrite ... break;,重写后不会重新匹配 location,直接用当前 location 处理新 URI; - 若用
rewrite ... redirect;或rewrite ... permanent;,则直接返回 302/301,不再进入后续处理; - 若用
rewrite ... last;,重写后会**重新发起一轮 location 匹配**(相当于内部跳转),可能触发其他 location 块,容易引发循环——必须确保重写后的 URI 不再匹配原 location; -
rewrite在if块中使用需格外谨慎(Nginx 官方不推荐),因为if内的 rewrite 行为受嵌套限制,且可能绕过正常 location 流程。
常见正确写法示例(带说明)
✅ 内部路径改写(不暴露给客户端):
把 /old-path/xxx 映射到 /new-api/xxx,浏览器地址栏不变:
location /old-path/ {
rewrite ^/old-path/(.*)$ /new-api/$1 break;
proxy_pass http://backend;
}
⚠️ 注意:break 阻止重新匹配,proxy_pass 使用改写后的 URI。
✅ 强制外部重定向(地址栏变化):
将旧域名路径永久跳转到新路径:
location /legacy/ {
rewrite ^/legacy/(.*)$ https://example.com/v2/$1 permanent;
}
⚠️ 此处用 permanent(301)或 redirect(302),无需 break 或 last,指令执行即返回响应。
✅ 配合正则捕获与条件判断(慎用 if):
仅当请求参数含 v=1 时重写(非推荐做法,但有时需兼容):
location /content/ {
if ($args ~ "v=1") {
rewrite ^/content/(.*)$ /content_v1/$1 break;
}
proxy_pass http://origin;
}
⚠️ 更健壮的做法是用 map 提前定义变量,避免 if + rewrite 组合。
必须避开的典型错误
-
在
location = /中用rewrite / /home/ last;:会导致无限循环,因为重写后仍匹配location = /;应改用break或换 location 块匹配/home/; -
忽略 URI 开头斜杠一致性:rewrite 目标以
/开头表示绝对路径,不加则相对当前 location;例如rewrite /a/b /c和rewrite /a/b c效果完全不同; -
在
proxy_pass后写 rewrite:无效,rewrite 必须在 proxy_pass 之前,否则已被转发; -
用
last却没提供能匹配的新 location:导致 404,重写后 URI 无对应 location 处理。
调试技巧:确认 rewrite 是否生效
开启 Nginx 重写日志快速验证逻辑(仅开发环境):
rewrite_log on; error_log /var/log/nginx/rewrite.log notice;
每条 rewrite 执行都会记录匹配、替换过程,方便定位是否命中、是否被覆盖或循环。


















