Nginx添加子路径引发无限重定向循环问题排查
解决Nginx将所有请求重定向到子路径时的无限循环问题
我来帮你分析下问题所在,以及怎么修复这个无限循环的问题。
首先,你当前的rewrite规则:
rewrite ^/(?!main).*$ /main/$1;
有两个核心问题导致了无限循环:
捕获分组缺失:你的正则表达式里没有定义捕获分组,所以
$1其实是空值。当请求/时,会被重写成/main/(因为$1为空),而当Nginx内部处理/main/这个请求时,虽然你的负向预查(?!main)理论上不会匹配它,但由于Nginx的rewrite规则默认是内部重定向(相当于发起了一个新的内部请求),如果没有明确的终止flag,可能会触发后续的rewrite规则检查,导致意外循环。缺少rewrite flag:没有添加
last或break这类终止flag,Nginx会在执行完当前rewrite后,继续从头检查所有的rewrite规则,这就埋下了循环的隐患。
修复后的配置方案
你可以把规则改成这样,同时解决这两个问题:
server { listen 80 default; server_name example.com; # 匹配所有不是以/main开头的请求 rewrite ^/(?!main)(.*)$ /main$1 last; }
这里做了两处关键调整:
- 给正则表达式加上了捕获分组
(.*),这样$1就能正确捕获到/之后的所有内容(包括空值),比如:- 请求
/→ 重写成/main - 请求
/faq→ 重写成/main/faq
- 请求
- 添加了
lastflag,告诉Nginx执行完这条rewrite后,停止当前阶段的规则检查,直接用新的路径去匹配location规则,避免重复触发rewrite。
额外说明
如果你需要的是外部重定向(让浏览器地址栏显示新的URL),而不是内部重写,可以把last换成permanent(永久重定向,HTTP 301)或者redirect(临时重定向,HTTP 302),比如:
rewrite ^/(?!main)(.*)$ /main$1 permanent;
这样就能完美实现你想要的效果:所有请求都会被正确导向/main子路径,同时不会出现无限循环的问题。
内容的提问来源于stack exchange,提问作者Yi Zhou
相关产品推荐
相关产品推荐

