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

使用RequestWrapper改请求头后,Jetty代理转发原请求的问题排查

问题解决:Jetty AsyncProxyServlet未使用Filter包装后的请求头

问题原因

你的MyFilter通过HttpServletRequestWrapper修改请求头后,rewriteTarget能正确获取到修改后的值,但AsyncProxyServlet在构建实际发送的代理请求时,默认逻辑并未复用包装后的请求头信息,而是直接从原始请求或内部默认逻辑读取,导致修改的头没有被带到目标URL。

解决方案

1. 确保RequestWrapper的头方法重写正确

首先确认你的MyRequestWrapper完整重写了所有请求头相关方法,保证外部能正确读取修改后的头:

public class MyRequestWrapper extends HttpServletRequestWrapper {
    private final Map<String, String> customHeaders;

    public MyRequestWrapper(HttpServletRequest request) {
        super(request);
        customHeaders = new HashMap<>();
        // 替换目标请求头
        customHeaders.put("需要修改的头名称", "修改后的值");
    }

    @Override
    public String getHeader(String name) {
        return customHeaders.containsKey(name) ? customHeaders.get(name) : super.getHeader(name);
    }

    @Override
    public Enumeration<String> getHeaders(String name) {
        if (customHeaders.containsKey(name)) {
            return Collections.enumeration(Collections.singletonList(customHeaders.get(name)));
        }
        return super.getHeaders(name);
    }

    @Override
    public Enumeration<String> getHeaderNames() {
        Set<String> headerNames = new HashSet<>(Collections.list(super.getHeaderNames()));
        headerNames.addAll(customHeaders.keySet());
        return Collections.enumeration(headerNames);
    }
}

2. 重写AsyncProxyServlet的代理请求构建方法

在你的AdminProxyServlet中,重写onProxyRequest或newProxyRequest方法,手动将包装后的请求头复制到代理请求中:

方式一:重写onProxyRequest(推荐,更简洁)

public class AdminProxyServlet extends AsyncProxyServlet implements Watcher {
    @Override
    protected String rewriteTarget(final HttpServletRequest request) {
        // 你的URL修改逻辑
        return super.rewriteTarget(request);
    }

    @Override
    protected void onProxyRequest(HttpServletRequest request, ProxyRequest proxyRequest) {
        super.onProxyRequest(request, proxyRequest);
        
        // 清空代理请求中原有的头,然后复制包装后的请求头
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            proxyRequest.headers().remove(headerName);
            
            Enumeration<String> headerValues = request.getHeaders(headerName);
            while (headerValues.hasMoreElements()) {
                proxyRequest.header(headerName, headerValues.nextElement());
            }
        }
    }
}

方式二:重写newProxyRequest

public class AdminProxyServlet extends AsyncProxyServlet implements Watcher {
    @Override
    protected String rewriteTarget(final HttpServletRequest request) {
        // 你的URL修改逻辑
        return super.rewriteTarget(request);
    }

    @Override
    protected ProxyRequest newProxyRequest(HttpServletRequest request, String rewrittenTarget) throws IOException {
        ProxyRequest proxyRequest = super.newProxyRequest(request, rewrittenTarget);
        
        // 复制包装后的请求头到代理请求
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            proxyRequest.headers().remove(headerName);
            
            Enumeration<String> headerValues = request.getHeaders(headerName);
            while (headerValues.hasMoreElements()) {
                proxyRequest.header(headerName, headerValues.nextElement());
            }
        }
        
        return proxyRequest;
    }
}

原理说明

Jetty的AsyncProxyServlet默认实现仅复制部分标准请求头,或者未完全复用传入的HttpServletRequest实例的头信息。通过上述重写,我们强制将包装后的请求头全部覆盖到代理请求中,确保修改后的头被正确传递到目标URL。

内容的提问来源于stack exchange,提问作者user2007260

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 10:37:32