Apache ProxyPass仅代理URL页面但无法代理页面资源的问题求助
问题场景
我当前使用Oracle HTTP Server 12.2.1.4,配置的代理规则如下:
ProxyPassMatch ^/foo/bar/(.+)$ https://xyz.domain.net/$1 ProxyPassReverse ^/foo/bar/(.+)$ https://xyz.domain.net/$1 ProxyPreserveHost Off
想要实现的效果是把https://my.website.com/foo/bar/home映射到https://xyz.domain.net/home。目前页面内容能正常加载,但页面里的JS、字体等资源全部报404错误:比如目标站点的页面会请求https://xyz.domain.net/scripts/index.js,但通过代理访问时,浏览器却去请求https://my.website.com/scripts/index.js,自然找不到资源。试过开启ProxyPreserveHost On,但会触发目标站点的403错误,想知道还需要添加什么配置才能让资源也正常代理?
解决方案
你遇到的核心问题是目标页面中的资源引用使用了根路径开头的绝对地址,浏览器会基于当前访问的域名解析这些路径,而非代理路径。结合Oracle HTTP Server的特性,给你两个可行的解决办法:
方案1:用mod_proxy_html重写页面内的URL
Oracle HTTP Server基于Apache,自带mod_proxy_html模块,可以自动修改响应内容里的URL,把目标站点的根路径替换成你的代理前缀。
在现有配置后添加以下规则:
# 启用HTML内容重写功能 ProxyHTMLEnable On # 将目标站点的绝对URL替换为代理路径 ProxyHTMLURLMap https://xyz.domain.net /foo/bar # 处理页面中根路径开头的资源引用 ProxyHTMLURLMap / /foo/bar/
配置完成后,页面里所有类似/scripts/index.js的资源路径都会被重写成/foo/bar/scripts/index.js,浏览器就会通过代理去请求目标站点的资源了。
方案2:调整ProxyPass规则覆盖所有子路径
如果目标站点的所有资源都部署在根目录下,可以把ProxyPass规则改成更宽泛的匹配,确保所有/foo/bar/开头的请求都被代理:
ProxyPass /foo/bar/ https://xyz.domain.net/ ProxyPassReverse /foo/bar/ https://xyz.domain.net/
这个配置比ProxyPassMatch更简洁,能覆盖所有子路径请求,但如果页面里的资源是根路径开头的绝对地址,还是需要配合方案1的URL重写才能生效。
关于ProxyPreserveHost的说明
开启ProxyPreserveHost On后出现403,是因为目标站点(xyz.domain.net)可能做了主机头校验,只允许自身域名的请求访问,所以这个选项不适合你的场景,保持ProxyPreserveHost Off即可。
最后,修改配置后记得重启Oracle HTTP Server让设置生效哦!
备注:内容来源于stack exchange,提问作者Ress

