应使用 proxy_redirect 而非 rewrite 修正后端返回的带端口 location 响应头;proxy_redirect 专用于反向代理中重写上游跳转地址,需置于 location 块内 proxy_pass 之后,并配合 proxy_set_header 透传协议与主机信息。

直接用 rewrite 指令处理带端口号的跳转地址,不是正确做法。Nginx 的 rewrite 是改请求路径、做客户端重定向或内部重写,它不碰后端返回的 Location 响应头——而带端口的跳转问题(比如 Location: http://10.1.2.3:8080/login)恰恰出在响应头上。
真正该用 proxy_redirect,不是 rewrite
proxy_redirect 是 Nginx 专为修正后端返回的 Location 和 Refresh 头设计的指令。它只作用于反向代理场景中上游服务发出的跳转响应,把内网地址、错误端口、本地域名等替换成用户能访问的公网地址。
- 它不改变请求本身,也不触发浏览器跳转,只是“悄悄”改掉响应头里的 URL
- 你看到的
http://192.168.1.100:8080/callback这类地址,必须靠proxy_redirect重写,rewrite完全无效 - 指令必须放在
location块里,且要写在proxy_pass之后
匹配并替换含端口的绝对 URL
后端常返回形如 http://backend:3000/path 或 http://172.18.0.5:8080/api/login 的地址。用正则可统一剥离协议、主机和端口,只保留路径:
- 基础写法(适配 HTTP + 任意主机+端口):
proxy_redirect ~^http://[^/]+(?::\d+)?(/.*)$ $scheme://$host$1; - 增强写法(同时兼容 http 和 https):
proxy_redirect ~^https?://[^/]+(?::\d+)?(/.*)$ $scheme://$host$1; - 说明:
[^/]+匹配主机名或 IP,(?::\d+)?表示可选的冒号加端口号,(/.*)捕获路径部分,$1就是这个路径
注意协议一致性与请求头透传
如果用户访问的是 https://example.com,但后端生成的跳转仍是 http://...,光靠 proxy_redirect 只能修路径,修不了协议降级。这时必须让后端知道真实协议:
- 务必加上:
proxy_set_header X-Forwarded-Proto $scheme; - 同时配好:
proxy_set_header Host $host;和proxy_set_header X-Real-IP $remote_addr; - 否则后端可能继续返回
http://开头的地址,导致下次跳转又失效
验证是否生效的实操方法
别只看配置文件,要用真实响应确认效果:
- 用
curl -I https://your-domain.com/some-path查看返回的Location:行是否已变成https://your-domain.com/xxx - 开启 Nginx error_log 到
info级别,日志里会记录proxy_redirect是否成功匹配并替换 - 常见失败原因:正则末尾多空格、漏分号、
proxy_redirect写在proxy_pass前面、$scheme在非 HTTPS 环境下为空











