Java HTTP反向代理及响应HTML URL重写解决方案咨询
解决反向代理中目标应用绝对URL路径的重写问题
看起来你踩了反向代理里很常见的一个坑——目标应用输出的绝对路径资源没有带上你的代理前缀,导致客户端直接请求根路径去了。下面给你几个实用的解决方案,结合你已经在用的HTTP-Proxy-Servlet和其他工具:
方案一:扩展HTTP-Proxy-Servlet,自定义响应内容重写
既然你已经在用HTTP-Proxy-Servlet,直接扩展它来处理响应内容的URL替换是最直接的方式,完全可控。
- 继承
org.mitre.dsmiley.httpproxy.ProxyServlet,重写它处理响应的方法。比如你可以拦截响应体,把所有以/开头的绝对路径替换成/proxy/前缀:
public class RewritingProxyServlet extends ProxyServlet { @Override protected void copyResponseEntity(HttpServletResponse response, HttpResponse proxyResponse) throws IOException { // 先获取原始响应内容 String responseBody = EntityUtils.toString(proxyResponse.getEntity(), StandardCharsets.UTF_8); // 替换HTML里的绝对路径:匹配 href="/xxx"、src="/xxx" 这类模式 String rewrittenBody = responseBody.replaceAll("(href|src)=\"/(?!proxy/)", "$1=\"/proxy/"); // 可选:处理JS里的路径,比如 window.location = '/xxx' rewrittenBody = rewrittenBody.replaceAll("(window\\.location|location\\.href) = '/(?!proxy/)", "$1 = '/proxy/"); // 设置新的响应内容和长度 response.setContentLength(rewrittenBody.getBytes(StandardCharsets.UTF_8).length); response.getWriter().write(rewrittenBody); } }
- 在web.xml或者Servlet 3.0+的注解里配置这个自定义的Servlet,替换原来的ProxyServlet。
这个方案的好处是你可以精确控制哪些内容需要重写,适配各种场景(HTML、JS、CSS里的URL),但需要自己处理编码、响应长度等细节,比如如果响应是二进制文件(图片、视频),要跳过替换逻辑。
方案二:用Tuckey UrlRewrite实现出站响应重写
你之前觉得Tuckey只能处理入站请求,其实它支持出站规则,可以修改返回给客户端的响应内容。只需要在urlrewrite.xml里添加对应的配置:
<!-- 入站代理规则:把/proxy/*转发到目标服务器 --> <rule> <from>^/proxy/(.*)$</from> <to type="proxy">http://other_app_to_proxy.com:9090/$1</to> </rule> <!-- 出站规则:修改HTML响应里的绝对路径,添加/proxy前缀 --> <outbound-rule> <!-- 匹配所有以/开头的路径,排除已经带/proxy/的 --> <from>^/(?!proxy/)(.*)$</from> <to>/proxy/$1</to> <!-- 只处理HTML内容,避免修改二进制文件 --> <condition type="response-content-type" operator="contains">text/html</condition> </outbound-rule> <!-- 可选:处理CSS里的url()路径 --> <outbound-rule> <from>url\('/(?!proxy/)(.*)'\)</from> <to>url('/proxy/$1')</to> <condition type="response-content-type" operator="contains">text/css</condition> </outbound-rule>
这个方案的优点是不用写Java代码,纯配置就能搞定大部分场景,适合快速解决问题。但如果目标应用里有复杂的URL(比如JS字符串里的动态路径),可能需要调整正则表达式来覆盖。
注意事项
- 区分绝对路径和相对路径:相对路径(比如
css/style.css)在代理后会自动基于当前页面的/proxy/路径解析,所以不需要处理;只有以/开头的绝对路径才需要重写。 - 避免误替换:要排除已经是
http://或https://开头的完整URL,以及已经带有/proxy/前缀的路径,否则会导致重复前缀。 - 响应编码:确保你处理响应内容时用了正确的编码,避免出现乱码。
内容的提问来源于stack exchange,提问作者snowindy
相关产品推荐
相关产品推荐

