Nginx可通过proxy_pass配合正则location捕获变量(如$1、$2)实现动态路由转发,支持拼接后端地址、rewrite重写URI及map指令基于Host等动态选择upstream,需注意匹配优先级、变量作用域与proxy_redirect配置。

Nginx 中可以通过 proxy_pass 配合 location 的正则匹配和捕获变量,实现动态路由转发。关键在于利用正则表达式捕获 URI 中的路径段或参数,并在 proxy_pass 后端地址中引用这些捕获组(如 $1、$2),从而将请求精准代理到不同上游服务。
使用带捕获的正则 location 匹配路径
在 location ~ ^/api/v(\d+)/(.+)$ 这类正则 location 中,$1 捕获版本号(如 1),$2 捕获后续路径(如 users/list)。Nginx 允许在 proxy_pass 中直接引用这些变量:
- 确保
proxy_pass末尾不带斜杠(否则会丢弃匹配路径) - 若后端需要保留原始路径结构,把捕获内容拼进 proxy_pass 地址或用
rewrite调整 - 例如:
proxy_pass http://backend-v$1/$2;将/api/v2/orders转发到http://backend-v2/orders
用 rewrite 重写 URI 再 proxy_pass(更灵活)
当需要修改路径结构、添加前缀、替换段或剥离前缀时,rewrite 更可控。注意加 break 或 last 标志避免循环:
-
rewrite ^/service/(\w+)/(.*)$ /$2 break;→ 把/service/user/profile改为/profile再转发 -
rewrite ^/v(\d+)/(.*)$ /api/v$1/$2 last;→ 重写后重新匹配 location,适合复杂路由逻辑 - 搭配
proxy_set_header X-Original-URI $request_uri;可透传原始路径给后端
捕获 Host 或请求头做动态 upstream(进阶用法)
单纯靠 URI 不够时,可结合 map 指令从 $host 或 $http_x_service 等提取目标服务名,再映射到 upstream 名称:
- 先定义:
map $host $upstream_backend { ~^api-(\w+)\.example\.com$ backend-$1; default backend-default; } - 再在 location 中:
proxy_pass http://$upstream_backend; - 这样
api-user.example.com自动转发到backend-user,无需多个 server 块
注意事项与常见坑
动态转发容易出错,需特别留意:
-
proxy_pass后跟变量(如$upstream)时,不能同时用proxy_redirect的默认重写,建议显式设置或设为off - 正则 location 优先级高于普通字符串 location,但低于 exact(
=)和 prefix(^~),注意匹配顺序 - 捕获变量只在当前 location 块内有效;跨块传递需用
set或map - 测试时用
curl -v查看实际转发地址和响应头,确认X-Forwarded-For、Host是否正确透传



















