You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java HTTP反向代理及响应HTML URL重写解决方案咨询

解决反向代理中目标应用绝对URL路径的重写问题

看起来你踩了反向代理里很常见的一个坑——目标应用输出的绝对路径资源没有带上你的代理前缀,导致客户端直接请求根路径去了。下面给你几个实用的解决方案,结合你已经在用的HTTP-Proxy-Servlet和其他工具:

方案一:扩展HTTP-Proxy-Servlet,自定义响应内容重写

既然你已经在用HTTP-Proxy-Servlet,直接扩展它来处理响应内容的URL替换是最直接的方式,完全可控。

  1. 继承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);
    }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:36:03