proxy_redirect 不支持变量因其在配置解析阶段编译,参数须为静态字符串;可通过 map 指令预定义映射关系实现动态重定向,或关闭 proxy_redirect 后用 headers-more 模块、sub_filter 或 Lua 手动重写 Location 响应头。

proxy_redirect 本身不支持变量(如 $host、$scheme),但可以通过组合 Nginx 的 map 指令 + 静态映射规则,或改用 proxy_redirect off + 手动重写响应头的方式,实现动态域名下重定向路径的自动修正。
为什么 proxy_redirect 不能直接用变量?
Nginx 的 proxy_redirect 指令在配置解析阶段就完成编译,其参数必须是静态字符串(如 "http://old.com/" "https://new.com/"),不支持运行时变量。若强行写成 proxy_redirect http://$host/ https://$host/;,Nginx 启动会报错:"proxy_redirect" directive invalid value。
方案一:用 map 构建动态重定向映射表(推荐)
适用于后端返回的重定向地址中 Host 可预判(如固定几类域名、子域名模式统一),通过 map 提前将变量转换为静态值,再供 proxy_redirect 使用:
- 在
http块中定义映射关系,例如按请求 Host 决定后端应看到的原始域名:
map $host $backend_origin {
~^(?<sub>.+)\.example\.com$ $sub.example.com;
default example.com;
}</sub>- 在 location 中使用该变量构造静态重定向规则(注意:需配合
proxy_set_header Host让后端生成正确跳转地址):
location /api/ {
proxy_pass https://backend/;
proxy_set_header Host $backend_origin;
proxy_redirect https://$backend_origin/ /;
proxy_redirect http://$backend_origin/ /;
}这样当用户访问 user1.example.com/api/,后端返回 Location: https://user1.example.com/login,Nginx 就能匹配并重写为 /login(相对路径),避免浏览器跳转到错误域名。
方案二:关闭 proxy_redirect,手动改写 Location 响应头(更灵活)
当后端返回的重定向地址不可控(如含随机端口、多级子域、协议混用),建议禁用自动重写,改用 proxy_hide_header + add_header 或 Lua/OpenResty 动态处理:
- 先隐藏原始 Location 头:
- 再用
sub_filter替换响应体中的跳转链接(适合 HTML 响应): - 对纯响应头中的 Location,可借助
headers-more-nginx-module:
location / {
proxy_pass https://upstream;
proxy_redirect off;
proxy_hide_header Location;
<pre class="brush:php;toolbar:false;"># 若安装了 headers-more 模块
more_set_headers "Location: $scheme://$host$request_uri";
# ⚠️ 注意:这仅适用于所有重定向都应跳回当前请求地址的场景
}
更通用的做法是配合 OpenResty 的 ngx.header.Location 在 Lua 中做条件判断和替换,例如提取原 Location 中 path 部分,拼接当前 $scheme://$host。
关键注意事项
-
proxy_redirect默认只处理301/302/307/308响应中的Location头,不处理响应体内容; - 若后端返回的是绝对 URL 且协议与当前不一致(如 HTTPS 站点里返回 HTTP Location),需显式写出两种协议的重定向规则;
- 使用
sub_filter时务必加sub_filter_once off并设置proxy_buffering on,否则可能失效; - 所有方案都要确保
proxy_set_header Host $host或对应变量,否则后端生成的跳转地址仍会出错。











