как работает метод connectAsyn c из PlainTunnelingConnection в jdk11u6? - PullRequest
0 голосов
/ 26 марта 2020

В http клиент может построить туннель, используя метод CONNECT для подключения промежуточного прокси и, наконец, подключиться к исходному серверу (RF C 7230).

Я читаю исходный код jdk11u6 PlainTunnelingConnection (пакет jdk.internal. net .http). Я думаю, этот класс может быть применен java для построения туннеля. В последнее время я приведу здесь код, но позвольте мне объяснить, что меня смущает этот класс.

В этом классе есть делегат PlainHttpConnection, который сначала будет подключен к адресу адреса прокси (серверы HttpConnection). как соединение TCP)

Я вставляю свой вопрос в исходный код.

/**
 * A plain text socket tunnel through a proxy. Uses "CONNECT" but does not
 * encrypt. Used by WebSocket, as well as HTTP over SSL + Proxy.
 * Wrapped in SSLTunnelConnection or AsyncSSLTunnelConnection for encryption.
 */

final class PlainTunnelingConnection extends HttpConnection {

final PlainHttpConnection delegate;
final HttpHeaders proxyHeaders;
final InetSocketAddress proxyAddr;
private volatile boolean connected;

protected PlainTunnelingConnection(InetSocketAddress addr,
                                   InetSocketAddress proxy,
                                   HttpClientImpl client,
                                   HttpHeaders proxyHeaders) {
    super(addr, client);
    this.proxyAddr = proxy;
    this.proxyHeaders = proxyHeaders;
    delegate = new PlainHttpConnection(proxy, client);
}

@Override
public CompletableFuture<Void> connectAsync(Exchange<?> exchange) {
    if (debug.on()) debug.log("Connecting plain connection");
    return delegate.connectAsync(exchange)
        .thenCompose(unused -> delegate.finishConnect())
        .thenCompose((Void v) -> {
            if (debug.on()) debug.log("sending HTTP/1.1 CONNECT");
            HttpClientImpl client = client();
            assert client != null;
            // here, I guess that req is the new request that the proxy uses to connect the 
            // next inbound server
            HttpRequestImpl req = new HttpRequestImpl("CONNECT", address, proxyHeaders);
            MultiExchange<Void> mulEx = new MultiExchange<>(null, req,
                    client, discarding(), null, null);
            Exchange<Void> connectExchange = mulEx.getExchange();
            // why the exchange responses the delegate connection?
            return connectExchange
                    .responseAsyncImpl(delegate)
                     // who responses this resp ?
                    .thenCompose((Response resp) -> {
                        CompletableFuture<Void> cf = new MinimalFuture<>();
                        if (debug.on()) debug.log("got response: %d", resp.statusCode());
                        if (resp.statusCode() == 407) {
                            return connectExchange.ignoreBody().handle((r,t) -> {
                                // auth ...
                            }).thenCompose(Function.identity());
                        } else if (resp.statusCode() != 200) {
                            // build fail
                        } else {
                            // get the initial/remaining bytes
                            // successfully ....
                            cf.complete(null);
                        }
                        return cf;
                    })
                    .handle((result, ex) -> {
                        //...
                    })
                    .thenCompose(Function.identity());
        });
}
...