答案是必须正确配置proxy_set_header host以避免nginx错误重写而非丢失,应根据后端是否依赖host头选择$http_host或$host透传原始域名,禁用$proxy_host,并同步设置x-forwarded-proto、x-forwarded-host等头以支撑跳转与url构造。

关键不是“防止丢失”,而是避免 Nginx 错误重写 Host 字段,导致后端 Web 服务器(如 Tomcat、Spring Boot 内嵌容器、Node.js 等)因门牌号不匹配而拒收请求,最终返回 404 或跳转失败。
明确你要透传还是覆盖 Host
后端是否依赖 Host 头判断站点?这是配置前提:
- 如果后端是单站点服务(如只跑一个应用),且不校验 Host,可直接设为代理目标域名:
proxy_set_header Host jx3.top; - 如果后端托管多个虚拟主机(如 Tomcat 配置了多个
<host></host>),它会严格比对 Host 头来路由请求——这时必须把客户端真实访问的域名传过去,不能用 IP 或 upstream 名称。
正确选择变量:$http_host vs $host
这两个变量行为不同,选错就会出问题:
-
$http_host:原样转发客户端请求头里的 Host 值,含端口(如app.example.com:8080)。适合非标端口或需完整还原原始请求的场景。 -
$host:只取域名部分,自动去掉端口(如app.example.com)。适用于标准 HTTP/HTTPS(80/443),更简洁安全。 - 绝对不要用
$proxy_host:它等于 upstream 地址(如127.0.0.1:8080),会让后端以为请求来自本机,多数情况下触发 404。
补全配套请求头,支撑完整业务逻辑
仅修 Host 不够,后端生成跳转链接、构造绝对 URL 时还依赖协议和原始入口信息:
-
proxy_set_header X-Forwarded-Proto $scheme;—— 告诉后端当前是 http 还是 https,避免登录后跳成 http:// 引发混合内容或失败 -
proxy_set_header X-Forwarded-Host $http_host;—— 提供原始域名全貌,方便后端安全还原访问地址 -
proxy_set_header X-Real-IP $remote_addr;和proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;—— 保障日志准确与登录风控有效
检查配置生效范围与冲突
常见失效原因不是写错了,而是被覆盖了:
- 确保
proxy_set_header Host只在需要的location或server块里出现一次,嵌套块中重复定义会以后者为准 - 禁用
underscores_in_headers on;(除非你明确需要下划线 header),否则可能连带忽略X-Forwarded-Proto等关键头 - 用
curl -v http://your-domain.com/path查看请求发出时的 Host,并在后端打印req.headers.host对比,确认是否真正透传成功











