Nginx rewrite正则如何同时剥离/foo路径及后续/bar子目录前缀
Nginx 多层路径前缀剥离配置方案
别写那种松散的(foo)|(/bar)正则,这种无锚点的匹配很容易误命中路径中间的foo、bar字段,斜杠边界也卡不准。最稳妥的实现是利用Nginx原生的location匹配优先级做分层匹配,完全兼容原有逻辑,也不会出斜杠匹配的bug。
推荐写法(维护性、容错率最高)
Nginx匹配规则里,更长的前缀location优先级更高,加^~标记可以让前缀匹配命中后跳过后续正则检查,直接写两个location段分别处理两层逻辑即可,天然兼容带/不带尾部斜杠的场景:
server { listen 8080; server_name default; # 优先处理/foo/bar路径,剥离/foo/bar两层前缀 location ^~ /foo/bar/ { rewrite ^/foo/bar(/.*)$ $1 break; proxy_redirect https://example.com https://$host/; # 此处其余代理配置和下方/foo段保持一致即可 } # 原有逻辑保留,兜底所有其余/foo开头请求,仅剥离/foo单层前缀 location /foo/ { rewrite ^/foo(/.*)$ $1 break; proxy_redirect https://example.com https://$host/; } }
这种写法不需要额外处理尾部斜杠,Nginx会自动对访问/foo/bar(不带末尾斜杠)的请求做301补斜杠跳转,不会出现404。如果两个location里重复配置太多,可以把公共代理配置抽到上一级server块,或者用Nginx的include指令抽成公共片段。
单正则合并写法
如果一定要把逻辑合并到同一个location里,正则必须锚定路径起始位置,明确匹配顺序,写法如下:
# 先补不带尾部斜杠的跳转规则 location = /foo/bar { return 301 /foo/bar/; } location ~ ^/foo(?:/bar)?(/.*)$ { rewrite ^/foo(?:/bar)?(/.*)$ $1 break; proxy_redirect https://example.com https://$host/; }
这个正则的匹配逻辑:
- 强制路径以
/foo开头,避免误匹配其他路径段里的foo字段 (?:/bar)?表示/bar段为可选匹配,有就一起匹配到前缀部分剥离,没有就只剥/foo- 最后捕获剩余的真实路径段转发
避坑提示
- 不要用无起始锚点的正则写路径匹配,会误命中
/abc/foo/xxx、/foo/abc/bar/xxx这类不符合预期的路径 - 不需要复用的捕获组加
?:标记为非捕获组,能减少正则匹配的性能开销 - 不要随便调整rewrite的flag,用
break即可,不要换成last避免内部循环跳转
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

