必须启用proxypreservehost on,以阻止apache将host头替换为后端地址(如127.0.0.1:8080),确保后端通过request.getheader("host")直接获取真实域名api.example.com;该指令须与proxypass同处或内,不可用于.htaccess或全局配置。

要让后端服务(如 Spring Boot、Django 或 Express)拿到用户访问的真实域名(比如 api.example.com),关键不是“手动传”,而是**阻止 Apache 覆盖 Host 请求头**——默认它会把 Host 改成后端地址(如 127.0.0.1:8080)。正确做法是启用 ProxyPreserveHost on,并确保它和 ProxyPass 在同一作用域内。
必须开启 ProxyPreserveHost on
这个指令的作用是:保持客户端原始 Host 头不变,原样转发给后端。后端调用 request.getHeader("Host") 就能直接读到 api.example.com,而不是内网地址。
- 不加这行,后端生成的绝对链接、SAML 回调地址、重定向跳转都会出错
- 加了但位置不对,等于没加——它只在
<virtualhost></virtualhost>或<location></location>块内生效 - 不能写在
.htaccess或主配置顶层(如 httpd.conf 最外层)
必须和 ProxyPass 同处一个 VirtualHost 块
常见错误是把 ProxyPreserveHost on 放在所有 <virtualhost></virtualhost> 外面,或误以为“配一次全局生效”。它只对同级的 ProxyPass 规则起作用。
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
- 每个子域名对应一个
<virtualhost></virtualhost>,里面都要单独写ProxyPreserveHost on - 多个
ProxyPass规则(如 /api/ 和 /admin/)共存时,只需一份ProxyPreserveHost on,只要它们在同一块内 - 示例正确结构:
ServerName api.example.com
ProxyPreserveHost on
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
配合 ProxyPassReverse 防止重定向暴露内网地址
ProxyPass 只改请求,ProxyPassReverse 负责修正后端返回的响应头(比如 302 的 Location、Set-Cookie 的 Domain)。如果只配前者,用户点登录后可能被跳转到 http://127.0.0.1:8080/callback,直接失败。
- 两者的路径结尾必须严格一致:都带
/,或都不带 - 目标地址协议和端口要和后端实际监听的一致(HTTP 还是 HTTPS?端口是 8080 还是 3000?)
- 若后端也走 HTTPS,需额外启用
mod_proxy_ssl并设置SSLProxyEngine on
补充真实客户端信息(IP、协议)
仅靠 ProxyPreserveHost 只解决域名问题。后端若需识别用户真实 IP 或判断是否 HTTPS 访问,还需手动注入标准代理头:
-
RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}e"—— 传真实客户端 IP -
RequestHeader set X-Forwarded-Proto "https" env=HTTPS—— 传协议(HTTP/HTTPS) - 后端框架需主动读取这些头,例如 Spring Boot 默认信任
X-Forwarded-*,但某些部署需显式配置server.forward-headers-strategy=framework










