必须开启proxypreservehost on,否则apache会用后端地址(如127.0.0.1:8080)覆盖原始host头,导致后端无法获取真实域名(如api.example.com),引发400/404/502错误;该指令须与proxypass同处于或内,且需配套proxypassreverse防止302跳转暴露内网地址。

根本原因是 Apache 默认会用后端地址(比如 127.0.0.1:8080)覆盖原始 Host 请求头,导致后端应用调用 request.getServerName() 或 req.hostname 时拿到的是内网地址或 localhost,而非用户访问的真实域名(如 api.example.com)。
必须开启 ProxyPreserveHost on
这是最直接、最关键的配置。它告诉 Apache 不要重写 Host 头,而是原样转发客户端发起请求时携带的原始值。
- 只在
<virtualhost></virtualhost>、<location></location>或<proxy></proxy>块内生效,不能写在全局配置或.htaccess中 - 必须与
ProxyPass出现在同一作用域,且每个ProxyPass都需单独配一行,不继承 - 加了之后,后端通过
request.getHeader("Host")就能拿到api.example.com,而不是127.0.0.1:8080
配套加上 ProxyPassReverse
仅透传 Host 头还不够。后端返回 302 跳转时,响应头中的 Location 通常含内网路径,浏览器会直接请求错误地址。
PHP中文网提供Apache 2.4.62 官方 tar.gz 源码包下载,通过源码编译安装,开发者能够灵活定制模块、优化性能并精准控制安装路径,满足多样化的业务需求。
- 例如:
ProxyPassReverse / http://127.0.0.1:8080/会自动改写响应里的Location、Content-Location等 URL - 路径末尾斜杠必须严格一致:如果
ProxyPass /api/,那么ProxyPassReverse /api/ http://127.0.0.1:8080/ - 若后端服务实际部署在子路径(如
/v1),还需额外映射:ProxyPassReverse /api http://127.0.0.1:8080/v1
后端应用要主动读取 Host 头
Apache 透传了,但后端若不解析,依然无效。不同框架处理方式不同:
- Spring Boot:设
server.forward-headers-strategy=framework,确保ForwardedHeaderFilter生效 - Express(Node.js):执行
app.set('trust proxy', true),再用req.hostname - Django:启用
USE_X_FORWARDED_HOST = True,并配好SECURE_PROXY_SSL_HEADER - Tomcat:确认
RemoteIpValve已配置,或代码中优先读request.getHeader("Host")
避免混淆 X-Forwarded-Host 和 Host
X-Forwarded-Host 是可选补充头,不是标准 HTTP 头,部分框架默认不信任;而 Host 是 RFC 强制字段,绝大多数框架默认直接使用。
- 优先依赖
Host头还原域名,更简洁可靠 - 若需兼容多级代理或记录原始入口,可额外加
RequestHeader set X-Forwarded-Host "%{HTTP_HOST}e" - 不要同时设置
ProxyPreserveHost off又手动设X-Forwarded-Host——逻辑冲突,容易出错










