nginx 通过 proxy_redirect 修正后端302响应中的 location 头,将内网地址(如 http://192.168.1.100:8080/login)重写为公网可访问地址(如 $scheme://$host/login),需配合 proxy_pass、proxy_set_header 透传 host、x-forwarded-proto 等头,并用 curl -i 和 error_log info 级日志验证生效。

必须用 proxy_redirect 重写 Location 头
该指令专为处理 301/302 的 `Location` 和 `Refresh` 响应头设计,写在 `location` 块内、`proxy_pass` 之后:
- 若后端固定返回
http://127.0.0.1:3000/:proxy_redirect http://127.0.0.1:3000/ $scheme://$host/; - 若只改协议(比如后端总发
http://,但你要 HTTPS):proxy_redirect http:// https://; - 若代理子路径(如
location /admin/ { proxy_pass http://backend/; }),后端返回/login,需补前缀:proxy_redirect / /admin/; - 更通用的容器/云环境适配(推荐):
proxy_redirect ~^http://[^/]+(?::\d+)?(/.*)?$ $scheme://$host$1;
光改响应头不够,还得告诉后端真实请求信息
否则后端下次生成的 `Location` 还是错的。这几行 `proxy_set_header` 必须加全:
-
proxy_set_header Host $host;—— 防止后端误用 localhost 或内网名 -
proxy_set_header X-Forwarded-Proto $scheme;—— 明确告知 HTTP 还是 HTTPS,避免协议降级 -
proxy_set_header X-Real-IP $remote_addr;和X-Forwarded-For $proxy_add_x_forwarded_for;—— 保留真实客户端 IP
验证是否真生效,别只看配置
改完 reload 后,用真实请求确认效果:
- 执行
curl -I https://your-domain.com/login,检查返回的Location:是否已是https://your-domain.com/xxx格式 - 开启 Nginx 错误日志到
info级:error_log /var/log/nginx/error.log info;,可看到类似proxy_redirect: ... matched的匹配记录 - 对比直连后端的结果(
curl -I http://192.168.x.x:port/login)和经 Nginx 代理后的结果,确认是否被成功替换
额外提醒:302 本身不该被长期缓存
如果后端返回的是 302(临时跳转),Nginx 默认不缓存它。若想缓存,必须显式配置:
-
proxy_cache_valid 302 2m;—— 推荐 2~5 分钟,避免掩盖上游变动 - 注意不能写成
proxy_cache_valid 301 302 1h;,301 和 302 必须分开设,否则可能失效 - 确保
proxy_cache_key包含$args(如有查询参数),否则不同参数会共用一个缓存项











