排查 rewrite 冲突需明确生效规则及触发条件,用 curl -v 查跳转链和后端 uri,启用 debug 日志定位匹配路径,注意 location 优先级、if 作用域及 rewrite 标志(break/last/redirect/permanent)的正确使用。

排查多条 rewrite 规则冲突导致的业务逻辑混乱,核心是搞清“哪条规则真正生效”以及“它在什么条件下被触发”。浏览器看到的跳转或 404 往往只是表象,真实执行路径藏在 Nginx 内部匹配和重写流程里。
用 curl + -v 看清实际跳转链
别依赖浏览器——它会缓存 301、自动补斜杠、隐藏中间跳转。直接用 curl 模拟原始请求:
- 查重定向循环:curl -Iv http://example.com/path,观察 Location 头是否来回切换(比如 /old → /new → /old)
- 查内部重写结果:curl -v http://example.com/api/v1/user,看响应状态码和后端实际收到的 URI(配合后端 access log 或 nginx 的 $uri 变量)
- 带 Host 和 Scheme 验证:curl -v --header "Host: example.com" https://127.0.0.1/path,绕过 DNS 和证书,确认 HTTPS 流量是否被错误降级
打开 debug 日志,定位真实匹配路径
rewrite_log 在新版 Nginx(≥1.19.0)已废弃,必须用 error_log debug 级别日志:
- 确认 Nginx 编译含 --with-debug(运行 nginx -V | grep -o with-debug)
- 在 http 块中加:error_log /var/log/nginx/rewrite-debug.log debug;
- 重启后触发请求,日志会出现类似:
"using regex \"^/api/(.*)$\"
rewritten data: \"/backend/v1/$1\"
test location: \"/backend/\"
matched location: /backend/" - 用 tail -f /var/log/nginx/rewrite-debug.log | grep -E "(regex|rewritten|location)" 实时过滤关键行
检查 location 优先级与作用域嵌套
rewrite 不是全局生效,它严格受 location 块匹配顺序和 if 条件控制:
- 确认触发 rewrite 的 location 是否真的被命中:精确匹配(location = /path) > 前缀匹配(location ^~ /static) > 正则匹配(location ~ \.php$)
- if 块里的 rewrite 容易被忽略:if 判断只在当前 location 内有效,且 if 嵌套在正则 location 中时,$request_uri 可能已被前面的 rewrite 修改过
- 多个 server 块共用同一域名?检查 80 和 443 端口的 server 块是否各自配置了独立、无冲突的 rewrite 逻辑,避免 HTTPS 请求误入 HTTP 块被降级
验证 rewrite 标志是否用对
last、break、redirect、permanent 四个标志行为完全不同,混用极易导致意料外的跳转或代理失败:
- break:终止当前 location 内所有 rewrite,不重新匹配 location —— 适合内部路径改写(如 rewrite ^/api/(.*)$ /$1 break;)
- last:终止当前 rewrite,重新从头匹配 location —— 容易引发循环,除非你明确需要二次匹配
- redirect / permanent:返回 302 或 301 跳转 —— 仅用于外部重定向,不要在 proxy_pass 前用它改写路径
- proxy_pass 前若需路径改写,必须用 break,且 proxy_pass 地址末尾要带斜杠(如 proxy_pass http://backend/;),否则拼接出错











