nginx rewrite规则按配置顺序执行,匹配后遇break/last/redirect/permanent即终止;需开启rewrite_log和notice级error_log验证执行,注意location作用域与匹配优先级,避免宽松规则前置导致后续规则失效。

排查 Nginx Rewrite 规则顺序错误,核心是理解 rewrite 指令的执行时机和匹配优先级:它在请求 URI 解析后、location 匹配前执行,且按配置文件中出现的顺序依次尝试——一旦某条规则触发了 break、last、redirect 或 permanent,后续 rewrite 就不再执行。顺序错乱(比如本该先处理的规则写在后面,或被前面的通配规则“吃掉”)会导致重写不生效、跳转错误、甚至无限重定向。
确认 rewrite 是否真的被执行
开启 Nginx 的 rewrite 日志,是最直接的验证方式:
- 在
http、server或location块中添加:rewrite_log on; - 同时确保 error_log 级别为
notice或更低(如info):error_log /var/log/nginx/rewrite.log notice; - 重启 Nginx 后发起请求,查看日志中是否打印类似:
test.com [notice] ... using configuration "rewrite ^/old/(.*)$ /new/$1 break;"
若无任何 rewrite 日志输出,说明规则根本没匹配到,要检查 URI 和正则是否对得上。
检查 location 与 rewrite 的作用域关系
rewrite 不在所有 location 中都生效,尤其要注意:
- rewrite 写在
server块顶层 → 对所有进入该 server 的请求生效(但已被 location 分流的请求,可能绕过它); - rewrite 写在某个
location块内 → 只对该 location 匹配的请求生效; - 如果用了
location ~ \.php$这类正则 location,而你的 rewrite 是针对静态路径(如/api/v1/xxx),但 rewrite 却放在了location /里,就可能因 location 匹配优先级更高而“跳过”rewrite; - 典型陷阱:把 rewrite 放在
location /中,但实际请求命中的是更精确的location /static/,导致 rewrite 完全不运行。
验证规则间是否发生“覆盖”或“截断”
多条 rewrite 共存时,顺序和 flag 决定行为:
-
last:终止当前 location 的 rewrite,重新匹配 location(相当于内部重定向),后续 rewrite 不执行; -
break:停止当前块内所有 rewrite,不重新匹配 location; -
redirect/permanent:返回 302/301,请求结束,后续规则无效; - 常见错误:前面一条宽松规则(如
rewrite ^/(.*)$ /index.php?path=$1 last;)放在最前,就把所有请求都“兜底”了,后面更具体的规则(如rewrite ^/user/(\d+)$ /api/user?id=$1 break;)永远没机会执行。
用 curl + -v 和 access_log 辅助定位
结合 HTTP 响应头和访问日志交叉验证:
- 用
curl -v http://your.site/xxx查看实际响应状态码和 Location 头,判断是否发生了意料外的跳转; - 在对应 location 中临时加
access_log /var/log/nginx/debug.log main;,并确保 log_format 包含$request_uri和$uri,对比原始请求、重写后 URI、最终匹配的 location; - 例如:请求
/old/path,access_log 显示request_uri="/old/path"但uri="/new/path",说明 rewrite 生效;若两者一致,则未触发。











