proxy_redirect本身不解决协议识别问题,必须配置proxy_set_header X-Forwarded-Proto $scheme;并启用后端信任该头,否则后端误判HTTP导致重定向死循环;proxy_redirect仅用于重写后端返回的Location/Refresh响应头。

这个问题本质不是 proxy_redirect 能直接解决的,而是它常被误用的典型场景。proxy_redirect 只负责改写后端响应头里的 Location 和 Refresh 字段,它不参与协议识别,也不影响后端应用读取原始请求协议的能力。
真正要解决的是后端拿不到 HTTPS 协议
后端应用(比如 PHP、Node.js、Java)判断协议是否为 HTTPS,通常依赖两个关键信息:
- X-Forwarded-Proto 请求头 —— 这是代理层告诉后端“用户实际用什么协议访问”的标准方式
- HTTP_X_FORWARDED_PROTO 环境变量(或等效字段)—— 后端框架从中提取协议值
如果 Nginx 没传这个头,或者传了但后端没启用信任代理配置,就会始终认为是 HTTP。
必须配齐的三项基础设置
在反向代理的 location 或 server 块中,这三行缺一不可:
- proxy_set_header X-Forwarded-Proto $scheme; —— 把当前 Nginx 接收请求时的协议(https 或 http)原样透传给后端
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; —— 补全真实客户端 IP 链路
- proxy_set_header Host $host; —— 避免后端因 Host 错误生成错误跳转
proxy_redirect 在这里起什么作用?
它只在后端自己返回 302/301 重定向时才生效。例如:
- 后端返回
Location: http://example.com/admin(硬编码 HTTP) - 用户本是通过
https://example.com/login访问的 - 这时就需要:
proxy_redirect http:// example.com/ https:// example.com/;
更安全通用的写法是利用变量动态适配:
⚠️ 已弃用 — 该技能已拆分为两个独立技能,以提升模块化程度:**webchat-https-proxy**(HTTPS/WSS 反向代理)和 **webchat-voi...**
proxy_redirect ~^http://[^/]+(/.*)?$ $scheme://$host$1;
这条规则会把所有以 http:// 开头的 Location 响应头,自动替换成当前请求的协议($scheme)和域名($host),避免 HTTPS 被降级为 HTTP。
后端也要配合验证
光靠 Nginx 设置还不够,后端必须启用对 X-Forwarded-* 头的信任:
- WordPress:在 wp-config.php 中加
$_SERVER['HTTPS'] = 'on';或使用插件识别 X-Forwarded-Proto - Laravel:在 AppServiceProvider 的 boot() 中调用
URL::forceScheme('https');,或配置 trusted proxies - Spring Boot:设
server.forward-headers-strategy=framework并配置server.tomcat.remoteip.remote-ip-header=x-forwarded-for
否则即使 Nginx 传了头,后端也会忽略它。










