排查 nginx rewrite 无限循环重定向故障,核心在于检查 `return` 或 `rewrite ... last` 是否导致请求 url 与匹配规则重复命中。通过开启 `error_log` 的 debug 级别并观察 `rewrite log`,可以捕获具体的 uri 变化路径,从而定位导致死循环的规则。

如何查看 Nginx 的重写日志
直接回答:在 Nginx 配置文件中启用 `rewrite_log on;` 即可在 error.log 中记录每次重写行为。这是排查的第一步,用于确认哪些规则被触发以及返回的状态码。

server {
listen 80;
server_name example.com;
# 开启重写日志,级别设为 info 或 debug
rewrite_log on;
location / {
# 示例规则:将 /old 重定向到 /new
rewrite ^/old$ /new last;
proxy_pass http://backend;
}
}
上述配置中,`rewrite_log on;` 是全局或 server 块指令。当请求进入时,Nginx 会在 error.log 中输出类似 `[info] 12345#67890: *1 rewrite index: "/old" -> "/new"` 的日志。如果发生循环,你会看到同一组 URI 反复出现。注意,`last` 表示当前重写完成,重新开始新一轮 location 匹配;而 `break` 则停止重写并直接使用当前 URI。理解这两者的区别是避免循环的关键。
如何识别并修复常见的循环模式
直接回答:最常见的循环发生在重写目标 URI 再次匹配原规则时。例如,将 `/api/v1` 重写为 `/api/v1`,或者重写到自身所在的 location 块且未改变 URI。修复方法是确保重写后的 URI 不再匹配触发该重写的条件,或使用 `if` 语句进行自我排除。

# 错误示例:可能导致循环
location /app {
# 如果 $request_uri 已经是 /app,这行会再次匹配
rewrite ^/app$ /app permanent;
}
# 正确示例:添加条件判断
location /app {
if ($request_uri ~ ^/app$) {
return 200 "Already at root";
}
rewrite ^/app/(.*)$ /app/$1 last;
}
在上面的代码中,第一个例子展示了典型的无限循环:请求 `/app` 被重写为 `/app`,然后再次进入 location 块,再次匹配规则,形成死循环。第二个例子通过 `if` 语句显式处理了这种情况,避免了循环。另一种更优雅的方式是使用 `rewrite` 的正则表达式确保 URI 发生变化,例如从 `/v1/resource` 重写为 `/v2/resource`,并确保 `/v2/resource` 不会再次触发 `/v1` 的规则。此外,使用 `permanent` (301) 或 `redirect` (302) 代替 `last` 也可以帮助浏览器缓存最终结果,减少服务器端的重复处理,但根本解决仍需确保逻辑无环。
基于特定输入 /test 的条件判断问题
直接回答:当输入 URI 为 `/test` 时,若配置中包含 `rewrite ^/test$ /test last;`,将导致无限循环。因为 `last` 会重启 location 匹配,而 `/test` 依然匹配该规则。解决方法是移除该规则或修改为目标不同的 URI。











