proxy_redirect 不处理缓存,仅实时改写上游返回的301/302响应头;需结合$scheme、$host等变量动态构造目标URL,确保协议、域名、端口、子路径与当前请求上下文一致。

proxy_redirect 本身不处理缓存,也不自动感知或刷新缓存中的重定向响应。它只在每次上游返回 301/302 响应时实时改写 Location 或 Refresh 头。所谓“缓存重定向场景下的全路径自动对齐”,实际是指:当后端服务返回的重定向 URL 因协议、主机、端口或子路径不一致,导致客户端(或中间 CDN/浏览器缓存)误存错误跳转地址时,如何通过 proxy_redirect 配合变量实现动态、准确、免硬编码的路径修正。
关键不在“缓存控制”,而在让每次重定向响应都即时、正确地对齐当前请求的完整上下文(协议 + 域名 + 端口 + 路径前缀)。以下是可落地的配置逻辑和建议:
✅ 使用 $scheme、$host、$server_port 动态构造目标前缀
避免写死域名或协议,尤其在多环境(dev/staging/prod)、HTTPS 卸载、或端口映射(如 443→8080)场景下:
location /app/ {
proxy_pass http://127.0.0.1:3000/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
# 将后端返回的任何 http://xxx 或 https://xxx 绝对路径,统一重写为当前请求的真实对外地址
proxy_redirect ~^https?://[^/]+(?::\d+)?/(.*)$ $scheme://$host/$1;
}说明:
- 正则
~^https?://[^/]+(?::\d+)?/(.*)$匹配任意协议 + 任意主机 + 可选端口 + 路径部分; -
$1提取原始路径(如/login?next=/admin),拼接到$scheme://$host/后,自然保留了用户访问时的协议(HTTP/HTTPS)、域名、端口(若非标准); - 不依赖后端是否返回
http://localhost:3000还是https://dev.example.com,全部一视同仁归一化。
✅ 子路径代理(如 /api/ → /)时,用相对路径重写补上前缀
当 proxy_pass 剥离了 location 前缀(如 location /api/ { proxy_pass http://backend/; }),而后端返回 Location: /dashboard,默认会跳到 https://example.com/dashboard(丢失 /api/)。此时需显式补回:
location /api/ {
proxy_pass http://backend/;
# 后端返回的 /dashboard → 改为 /api/dashboard
proxy_redirect / /api/;
}⚠️ 注意:proxy_redirect / /api/; 中第一个 / 是匹配后端返回的绝对路径起始符,不是 Nginx 的 location 路径;它仅在后端返回 Location: /xxx 时生效。若后端返回 http://xxx/xxx,该规则不触发,需配合上面的正则规则。
✅ 禁用默认推导,防止 proxy_redirect default 产生意外覆盖
proxy_redirect default 会基于 proxy_pass 和 location 自动推导替换规则,但易出错——尤其在 proxy_pass 末尾有无 /、路径嵌套、或多个 location 共享 upstream 时。推荐显式关闭并自定义:
location /admin/ {
proxy_pass http://admin-svc:8000/;
proxy_redirect off; # 先关掉默认行为
proxy_redirect ~^https?://[^/]+/(.*)$ $scheme://$host/admin/$1;
}这样可确保所有重定向都带 /admin/ 上下文,不会因 default 规则误匹配成 /。
✅ 配合 proxy_cache 时的注意事项
如果启用了 proxy_cache 缓存 302 响应(不推荐,但存在):
-
proxy_redirect仍会在缓存命中时执行(Nginx 在发送缓存响应前仍会应用 rewrite 指令); - 但前提是
proxy_redirect规则能匹配到缓存响应头中保存的原始Location值; - 所以务必保证你的正则或前缀规则兼容缓存中可能存在的各种历史返回格式(比如旧版后端曾返回
http://10.0.1.5:8080/,新版已切 HTTPS,但缓存未过期); - 更稳妥做法:给重定向响应加
Cache-Control: no-cache, no-store,或用proxy_cache_bypass $upstream_http_location;让含Location的响应不进缓存。
不复杂但容易忽略


















