Nginx支持通过proxy_pass结合变量实现动态代理,但变量必须为合法完整URI格式;推荐用map预定义可信后端映射,避免直接拼接风险变量,并利用add_header调试实际值。

Nginx 支持通过 proxy_pass 指令结合变量实现动态代理,让后端目标地址不再写死,而是根据请求头、URI、参数等运行时信息灵活决定。这在灰度发布、多租户路由、A/B 测试或网关统一转发等场景中非常实用。
变量必须是“合法的 URI 形式”
Nginx 要求 proxy_pass 后接的变量值必须能被解析为完整、规范的 URL(含协议和主机),否则会报错 "invalid URL prefix" 或直接 500。不能只写 $host:$port 或 http://$backend 这类不带路径或格式不全的表达式。
- ✅ 正确写法:
proxy_pass http://$upstream_host$request_uri; - ✅ 正确写法:
set $target "https://api-$env.example.com"; proxy_pass $target; - ❌ 错误写法:
proxy_pass http://$host;(缺少路径,且 $host 可能为空或含非法字符) - ❌ 错误写法:
proxy_pass $scheme://$host:$port;($scheme/$host/$port 在 server 块中不可用,仅限 rewrite 阶段部分变量)
推荐使用 map 预定义可信后端映射
直接在 location 中拼接变量风险高(如注入、空值、非法字符)。更安全的做法是先用 map 指令基于请求特征(如 Host、Header、Cookie)映射出预设的后端地址,再在 proxy_pass 中引用。
示例:按请求头 X-Env 分发到不同环境
map $http_x_env $backend {
default "http://default-api.internal";
"staging" "http://staging-api.internal";
"prod" "http://prod-api.internal";
}
然后在 location 中使用:
location /api/ {
proxy_pass $backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
注意变量作用域与执行阶段
Nginx 变量分两类:一类在配置加载时确定(如 $server_name),另一类在请求处理时生成(如 $arg_x、$http_user_agent)。只有后者可用于动态代理;但它们只能在 rewrite 或 proxy_pass 所在上下文中生效。
-
set和map定义的变量可在server或http块中声明,但值在每次请求时计算 -
$request_uri、$args、$host等始终可用;$scheme、$server_port在 server 块中可用,但在某些旧版本中proxy_pass不支持直接引用它们 - 避免在
if块中使用proxy_pass(Nginx 官方明确不推荐),改用map+proxy_pass $var
调试技巧:用 add_header 输出实际变量值
动态代理出错时,最有效的方式是把变量内容透传到响应头,确认它是否符合预期:
location /api/ {
add_header X-Used-Backend $backend;
add_header X-Request-URI $request_uri;
proxy_pass $backend;
}
然后用 curl -I 查看响应头,快速验证变量是否被正确赋值、有无空格或编码问题。

















