ProxyPreserveHost 必须设为 on 才能透传原始 Host 头,否则 Apache 会将其替换为后端地址(如 localhost:8080),导致后端无法识别真实域名(如 api.example.com),引发 400、404 或 502 错误。

必须设为 on,否则 Apache 会把请求头里的 Host 替换成后端地址(比如 localhost:8080),导致后端收不到用户实际访问的域名(如 api.example.com),进而出现 400、404 或 502 错误。
为什么 ProxyPreserveHost on 是关键一步
Apache 的 mod_proxy 默认会重写 Host 请求头,用代理目标地址覆盖原始值。这对依赖域名做路由、租户识别或生成绝对 URL 的后端(如 Spring Boot、Express、Django)是致命的——它可能生成 http://localhost:8080/login 这样的跳转链接,或拒绝非预期域名的请求。
- 开启后,原始 Host 头(如
Host: app.example.com)原样透传给后端 - 后端可通过
request.getHeader("Host")直接读取真实域名 - 比
X-Forwarded-Host更直接、更通用,多数框架默认信任 Host 头
配置位置和作用域不能错
该指令不是全局生效的,必须与 ProxyPass 在同一配置层级,否则无效。
⚠️ 已弃用 — 该技能已拆分为两个独立技能,以提升模块化程度:**webchat-https-proxy**(HTTPS/WSS 反向代理)和 **webchat-voi...**
- 只能放在
、或块内 - 不能写在主配置顶层(如 httpd.conf 最外层)
- 每个
ProxyPass规则若独立存在,需各自配ProxyPreserveHost on,不继承 - .htaccess 中完全不可用(属服务器级指令)
最小可用配置示例
以下是在虚拟主机中正确启用的典型写法:
<virtualhost>
ServerName api.example.com
ProxyPreserveHost on
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
</virtualhost>
-
ProxyPassReverse不可省略:它重写响应头中的Location、Content-Location等 URL,避免 302 跳转暴露内网地址 - 路径末尾斜杠必须一致:
/对应http://127.0.0.1:3000/,否则路径拼接出错 - 确认已启用模块:
a2enmod proxy proxy_http(Debian/Ubuntu)或检查LoadModule行已取消注释
常见问题排查提示
如果后端仍收到 127.0.0.1 或 localhost 作为 Host:
- 检查 Apache 配置语法:
apache2ctl configtest或apachectl -t - 查看错误日志,确认是否加载了
mod_proxy和mod_proxy_http - 抓包或在后端打印所有请求头,验证 Host 是否真的被转发
- 排除 Nginx 或 CDN 层提前改写 Host 头的可能(如 Cloudflare 默认不透传)










