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

如何配置Jetty的ConnectHandler将请求转发至上游代理处理CONNECT操作?

嘿,这个需求完全可以实现!默认的ConnectHandler确实没直接提供配置项让你转发到上游代理——毕竟它原本的设计就是自己完成SSL隧道的建立。不过我们可以通过扩展ConnectHandler来定制逻辑,下面是具体的可行方案:

方案:自定义扩展ConnectHandler实现转发

核心思路是继承Jetty的ConnectHandler,重写它处理CONNECT请求的核心方法,把原本直接连接目标服务器的逻辑改成连接上游代理,再把客户端的请求转发给上游代理处理。

具体实现步骤

1. 创建自定义ConnectHandler子类

重写handleConnect方法,这是处理CONNECT请求的核心入口。我们需要在这个方法里完成:解析目标地址、连接上游代理、发送CONNECT请求给上游代理、确认隧道建立、最后完成客户端和上游代理的双向数据转发。

2. 核心代码示例

这里给你一个简化版的实现框架,你可以根据实际需求补充细节:

import org.eclipse.jetty.server.handler.ConnectHandler;
import org.eclipse.jetty.server.Request;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.Socket;

public class ForwardingConnectHandler extends ConnectHandler {
    private final String upstreamProxyHost;
    private final int upstreamProxyPort;

    public ForwardingConnectHandler(String upstreamProxyHost, int upstreamProxyPort) {
        this.upstreamProxyHost = upstreamProxyHost;
        this.upstreamProxyPort = upstreamProxyPort;
    }

    @Override
    protected boolean handleConnect(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 解析CONNECT请求的目标地址,格式为 "host:port"
        String targetHostPort = target;

        try (Socket proxySocket = new Socket(upstreamProxyHost, upstreamProxyPort)) {
            // 向上游代理发送标准的CONNECT请求
            String connectRequest = String.format("CONNECT %s HTTP/1.1\r\nHost: %s\r\n\r\n", targetHostPort, targetHostPort);
            proxySocket.getOutputStream().write(connectRequest.getBytes());
            proxySocket.getOutputStream().flush();

            // 读取上游代理的响应,确认隧道是否建立成功
            byte[] buffer = new byte[1024];
            int readLen = proxySocket.getInputStream().read(buffer);
            if (readLen <= 0 || !new String(buffer, 0, readLen).contains("200")) {
                response.sendError(HttpServletResponse.SC_BAD_GATEWAY, "Upstream proxy failed to establish tunnel");
                baseRequest.setHandled(true);
                return true;
            }

            // 获取客户端的Socket连接
            Socket clientSocket = getServer().getHttpChannel(baseRequest).getEndPoint().getSocket();

            // 启动双向数据转发,复用ConnectHandler内置的转发逻辑
            startProxy(clientSocket, proxySocket, targetHostPort);
            baseRequest.setHandled(true);
            return true;
        } catch (Exception e) {
            response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Failed to connect to upstream proxy");
            baseRequest.setHandled(true);
            return true;
        }
    }
}

3. 配置并使用自定义Handler

在你的Jetty服务器初始化代码里,替换原来的ConnectHandler为这个自定义实现即可:

Server server = new Server(8080);
// 替换成你的上游代理地址和端口
ForwardingConnectHandler connectHandler = new ForwardingConnectHandler("your-upstream-proxy.com", 3128);
server.setHandler(connectHandler);
server.start();

注意事项

  • 异常处理:上面的代码是简化版,生产环境需要完善异常捕获和处理逻辑,比如代理连接超时、认证失败等场景
  • 代理认证:如果上游代理需要身份验证,你需要在发送CONNECT请求时添加Proxy-Authorization头
  • 性能优化:默认的startProxy方法使用单线程处理数据转发,高并发场景下可以考虑改用NIO或者线程池来优化

这样就能实现让Jetty的ConnectHandler把CONNECT请求转发到上游代理,由上游代理完成隧道建立操作了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:55:45