Nginx proxy_redirect 支持变量仅限 replacement 部分,redirect 部分需用正则字面量捕获路径,配合 $1~$9 和 $scheme、$host 等变量动态重写 Location/Refresh 响应头,但不处理 HTML 内容。

在 Nginx 反向代理静态资源时,后端服务(如 Node.js、Python Flask、或内部 CDN 接口)返回的 Location、Refresh 响应头或 HTML 中的绝对路径(如 /static/js/app.js、https://api.example.com/v1/data)常与前端反向代理的公开路径不一致,导致资源 404 或跳转错误。此时仅靠 proxy_pass 不够,需用 proxy_redirect 配合变量动态修正路径 —— 关键在于理解它支持变量、作用时机和匹配逻辑。
proxy_redirect 的变量支持与匹配原理
proxy_redirect 默认只支持字面量重写(如 proxy_redirect /old/ /new/;),但从 Nginx 1.1.11+ 开始,它允许在 replacement 部分使用变量(如 $scheme、$host、$request_uri 等),但 redirect 部分(即匹配部分)仍不支持正则变量,仅支持字面量或正则表达式字面量(~ 或 ~*)。真正实现“动态全路径修正”的核心是:用正则捕获原始响应头中的路径,再用变量构造新路径。
- 它只处理后端响应头中的
Location和Refresh字段,不影响 HTML 内容本身 - 匹配按配置顺序执行,首个成功匹配的规则生效;未匹配则保持原值
- 若启用
proxy_redirect default;,Nginx 会自动基于proxy_pass地址推导基础重写(适合简单场景,但无法满足变量化需求)
典型场景:代理到带路径前缀的后端并修正 302 跳转
假设你将 https://cdn.example.com/assets/ 反向代理到内网 http://10.0.1.5:8080/public/,而后端返回 Location: /public/images/logo.png,浏览器会请求 https://cdn.example.com/public/images/logo.png(404)。目标是将其改为 /assets/images/logo.png。
配置示例:
location /assets/ {
proxy_pass http://10.0.1.5:8080/public/;
proxy_redirect ~^/public(/.*)?$ /assets$1;
}
-
~^/public(/.*)?$捕获/public后的可选路径(如/public/css/main.css→ 捕获/css/main.css) -
/assets$1中$1是正则捕获组,实现路径平移 - 注意
proxy_pass末尾有/,确保/assets/xxx映射为/public/xxx,避免重复路径
跨协议/跨域跳转的动态重写(含变量)
当后端返回完整 URL(如 Location: http://internal-api.local/v1/auth),而你需要对外暴露为 https://api.example.com/v1/auth,且域名、协议需随请求动态变化(例如测试环境用 https://staging.example.com,生产用 https://api.example.com),这时必须用变量:
location /api/ {
proxy_pass http://10.0.2.10:3000/;
proxy_redirect ~^(http|https)://[^/]+(/.*)?$ $scheme://$host$1;
}
-
~^(http|https)://[^/]+(/.*)?$匹配任意协议 + 域名 + 路径,捕获路径部分到$1 -
$scheme://$host$1动态拼接当前请求的协议和 Host,再追加原始路径 - 确保
$host是可信的(建议配合underscores_in_headers on;和白名单valid_referers或严格server_name控制)
补充:HTML 内链接的修正需额外手段
proxy_redirect 不处理响应体内容。若后端返回的 HTML 中有 <script src="/static/app.js"></script>,仍需其他方式修正:
- 用
sub_filter替换响应体中的路径:sub_filter '/static/' '/assets/'; sub_filter_once off; - 更健壮的做法是让后端通过配置或请求头(如
X-Forwarded-Prefix: /assets)生成相对路径或上下文感知 URL - 现代方案倾向由前端构建时注入
PUBLIC_URL,避免运行时依赖 Nginx 重写
不复杂但容易忽略:变量只能用于 replacement,redirect 部分靠正则捕获;务必校验 proxy_pass 尾部斜杠与路径映射关系;涉及用户输入的变量(如 $args)需防范注入,优先使用确定性变量($scheme、$host、$1~$9)。


















