使用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
相关产品推荐
相关产品推荐

