nginx proxy_pass 支持变量需满足协议固定、变量仅含 host[:port]、启用 resolver(域名场景);推荐用 map 模块实现安全动态路由,并注意结尾 / 对路径拼接的影响。

Nginx 本身不支持直接在 proxy_pass 中使用任意变量(如 $backend)作为完整 URL,除非满足特定条件——主要是协议、主机、端口必须固定或能被 Nginx 静态解析。但通过合理配置,可以实现“动态转发到变量指定后端”的效果,关键在于绕过 URI 重写冲突、正确处理路径拼接,并启用必要的模块支持。
✅ 必须开启 resolver(DNS 动态解析)
如果后端地址是域名(如 $host_from_header 或 $upstream_var),Nginx 默认无法在运行时解析变量中的域名,会报错 "invalid URL prefix" 或 "no resolver defined"。需显式配置 DNS 解析器:
- 在
http或server块中添加:
resolver 8.8.8.8 114.114.114.114 valid=30s; - 确保变量值只含
host[:port](不能带http://或路径),例如:set $backend "api.example.com:8080"; -
proxy_pass http://$backend;才能生效(协议头http://必须写死,不可用变量)
✅ 正确构造变量:避免协议和路径混入
proxy_pass 后接变量时,Nginx 要求该变量仅表示“上游地址+端口”,其余部分(协议、URI)需静态声明或由 rewrite 控制:
- ❌ 错误写法(协议和路径用变量):
set $url "https://srv1:3000/v1";<br>proxy_pass $url;
→ 不支持 - ✅ 推荐写法(分离协议与地址):
set $backend "srv1:3000";<br>proxy_pass http://$backend/v1; # /v1 是静态后缀
- 若需不同路径,配合
rewrite提前处理:rewrite ^/api/(.*)$ /$1 break;<br>proxy_pass http://$backend;
✅ 使用 map 模块实现条件路由(更安全可控)
比在 location 中反复 set 更健壮,适合根据请求头、域名或路径映射后端:
- 在
http块中定义映射关系:
map $http_x_backend $upstream_host {
default "default-srv:8000";
"srv-a" "a.internal:8080";
"srv-b" "b.internal:9000";
} - 在 location 中使用:
proxy_pass http://$upstream_host; - 配合
resolver,即可实现按请求头动态选后端
✅ 注意 proxy\_pass 变量的 URI 处理逻辑
变量是否带结尾 /,直接影响路径拼接行为:
-
proxy_pass http://$backend;(无 URI)→ 原始请求路径完整透传
例:请求/api/user→ 转发到http://srv:8000/api/user -
proxy_pass http://$backend/;(有结尾/)→ 会剥离 location 匹配前缀
例:location/api/+proxy_pass http://$backend/;→/api/user变成/user - 务必统一风格,避免因斜杠缺失导致 404











