nginx反向代理中路径改写需区分内部转发(rewrite+break)与外部重定向(return/rewrite permanent),并严格匹配proxy_pass尾部斜杠规则:带/则截前缀拼接,不带/则透传原始uri;$request_uri保留查询参数,$uri不保留;避免if中proxy_pass,优先用map实现条件路由。

在 Nginx 反向代理中,请求路径的动态改写与重定向不是简单替换字符串,而是要结合 proxy_pass 的路径处理逻辑、rewrite 指令的执行时机以及客户端可见的重定向行为来协同实现。核心在于区分“内部转发路径改写”和“外部 301/302 重定向”,并准确控制 URI 变量(如 $uri、$request_uri、$1)的作用范围。
理解 proxy_pass 路径截断与拼接规则
Nginx 中 proxy_pass 后是否带路径,直接影响后端收到的 URI:
- 若
proxy_pass http://backend;(无尾随路径),Nginx 将原始请求 URI(包括 location 匹配部分)完整透传给后端; - 若
proxy_pass http://backend/api/;(带尾随斜杠),Nginx 会先移除 location 匹配的前缀,再拼接/api/,例如访问/v1/users匹配location /v1/,则后端收到/api/users; - 若
proxy_pass http://backend/api;(不带尾随斜杠),Nginx 不做路径替换,直接拼接,易导致路径错乱(如/v1/users→/api/v1/users),一般应避免。
用 rewrite 实现内部路径动态改写(不暴露给客户端)
当需根据请求参数、Header 或路径特征动态调整转发路径,且不希望浏览器地址栏变化时,使用 rewrite ... break;:
-
rewrite ^/app/(.*)$ /service/v2/$1 break;:将/app/user改写为/service/v2/user,然后继续匹配 location 或直接转发; - 必须加
break(而非last),否则会重新发起 location 匹配,可能引发循环或意外跳转; - 改写后的 URI 仅影响后续
proxy_pass行为,客户端无感知,适合 API 网关层的路由映射。
用 return 或 rewrite + redirect 实现外部重定向(改变浏览器地址)
当需要用户看到新 URL(如 SEO 迁移、路径标准化),用 return 301 或 rewrite ... permanent:
-
return 301 https://$host/new-path$request_uri;:强制跳转,高效且语义清晰; -
rewrite ^/old/(.*)$ /new/$1 permanent;:等价于 301,支持正则捕获; - 注意:
$request_uri包含原始 query string,而$uri不包含,重定向时通常应保留查询参数,优先用$request_uri; - 重定向发生在 proxy_pass 之前,所以它不会触发反向代理,而是直接返回响应给客户端。
组合场景:先改写路径再转发,并按条件重定向
实际中常需混合策略,例如对特定 User-Agent 返回重定向,其余正常代理:
- 用
map提前定义变量:map $http_user_agent $should_redirect {<br> ~*curl 1;<br> default 0;<br>} - 在 location 中判断:
if ($should_redirect) {<br> return 302 /api/v2$request_uri;<br>}
然后执行rewrite或直接proxy_pass。 - 避免在 if 块中使用
proxy_pass(Nginx 官方不推荐),推荐用map+ 多个 location 分流,更健壮。
不复杂但容易忽略。关键在理清 rewrite 执行阶段、proxy_pass 路径拼接规则、以及重定向与代理的本质区别。











