rewrite指令必须置于server或location块中,不可放于http顶层或if块(官方不推荐);server块内规则全局生效,location块内仅对匹配路径生效,if块仅限极少数场景且需配合return或set。

Nginx 的 URL 重写靠 rewrite 指令实现,但正则写错、flag 选错或位置放错,任一出问题都会导致跳转失效、循环重定向甚至 500 错误。
rewrite 应该放在哪儿?server、location、if 的区别很关键
别把 rewrite 塞进 if 块里——官方明确不推荐。if 是配置解析期判断,rewrite 是请求处理期执行,语义和时机不一致,容易偶发失效或匹配异常。
- server 块中:对所有请求生效,适合全局操作,比如强制跳转 HTTPS
- location 块中:只对匹配该路径的请求起作用,最常用也最安全
-
if 块中:仅允许极少数场景(如检查
$args或$host),且必须配合return或set,不能嵌套 rewrite
last 和 break 怎么选?关键看要不要重新匹配 location
两者都会终止当前块内后续 rewrite 执行,但行为完全不同:
-
last:重写后的新 URI 会重新进入 server 匹配流程,可能命中另一个 location —— 容易引发循环(比如
rewrite /a /b last+rewrite /b /a last),Nginx 限制最多 10 次重试,超限返回 500 - break:重写后不再重新匹配,直接用新 URI 在当前 location 内继续处理(比如找文件、proxy_pass)—— 更可控,适合内部路径改写
常见误用:location /api { rewrite ^/api/(.*)$ /v2/$1 last; } → 新 URI /v2/xxx 若没对应 location /v2,结果 404;换成 break 就直接在当前 location 下查找 /v2/xxx 文件
怎么让浏览器真正跳转?replacement 必须带协议头
redirect 和 permanent 的本质是返回 HTTP 状态码(302 / 301),但有个硬性条件:replacement 字符串必须以 http://、https:// 或 $scheme:// 开头,否则 Nginx 当作内部重写处理,地址栏不会变。
- 正确写法:
rewrite ^/old.html$ https://example.com/new.html permanent; - 错误写法:
rewrite ^/old.html$ /new.html permanent;→ 实际效果等同于last - 安全建议:用
$scheme替代硬编码协议,避免 HTTP/HTTPS 混用,例如:rewrite ^/login$ $scheme://$host/auth permanent;
正则捕获和变量引用要注意什么?
正则里用 () 捕获的内容,通过 $1、$2 引用,但注意:
-
$1只在当前 rewrite 行有效,不能跨行传递 - 想复用捕获内容,需在单行内完成全部替换逻辑,或改用
map+set配合 - 避免在正则中误写
\d(Nginx 默认不支持 \d,应写[0-9]或启用 PCRE 兼容模式)


















