src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java
changeset 51364 31d9e82b2e64
parent 49765 ee6f7a61f3a5
child 56868 67c7659ecda5
equal deleted inserted replaced
51363:a6fa2016cff1 51364:31d9e82b2e64
    24  */
    24  */
    25 
    25 
    26 package jdk.internal.net.http;
    26 package jdk.internal.net.http;
    27 
    27 
    28 import java.io.IOException;
    28 import java.io.IOException;
    29 import java.lang.System.Logger.Level;
       
    30 import java.net.InetSocketAddress;
    29 import java.net.InetSocketAddress;
       
    30 import java.net.http.HttpTimeoutException;
    31 import java.nio.ByteBuffer;
    31 import java.nio.ByteBuffer;
    32 import java.nio.channels.SocketChannel;
    32 import java.nio.channels.SocketChannel;
       
    33 import java.time.Duration;
    33 import java.util.concurrent.CompletableFuture;
    34 import java.util.concurrent.CompletableFuture;
       
    35 import java.util.concurrent.CompletionException;
    34 import java.util.function.Function;
    36 import java.util.function.Function;
    35 import java.net.http.HttpHeaders;
    37 import java.net.http.HttpHeaders;
    36 import jdk.internal.net.http.common.FlowTube;
    38 import jdk.internal.net.http.common.FlowTube;
    37 import jdk.internal.net.http.common.MinimalFuture;
    39 import jdk.internal.net.http.common.MinimalFuture;
    38 import static java.net.http.HttpResponse.BodyHandlers.discarding;
    40 import static java.net.http.HttpResponse.BodyHandlers.discarding;
    58         this.proxyHeaders = proxyHeaders;
    60         this.proxyHeaders = proxyHeaders;
    59         delegate = new PlainHttpConnection(proxy, client);
    61         delegate = new PlainHttpConnection(proxy, client);
    60     }
    62     }
    61 
    63 
    62     @Override
    64     @Override
    63     public CompletableFuture<Void> connectAsync() {
    65     public CompletableFuture<Void> connectAsync(Exchange<?> exchange) {
    64         if (debug.on()) debug.log("Connecting plain connection");
    66         if (debug.on()) debug.log("Connecting plain connection");
    65         return delegate.connectAsync()
    67         return delegate.connectAsync(exchange)
       
    68             .thenCompose(unused -> delegate.finishConnect())
    66             .thenCompose((Void v) -> {
    69             .thenCompose((Void v) -> {
    67                 if (debug.on()) debug.log("sending HTTP/1.1 CONNECT");
    70                 if (debug.on()) debug.log("sending HTTP/1.1 CONNECT");
    68                 HttpClientImpl client = client();
    71                 HttpClientImpl client = client();
    69                 assert client != null;
    72                 assert client != null;
    70                 HttpRequestImpl req = new HttpRequestImpl("CONNECT", address, proxyHeaders);
    73                 HttpRequestImpl req = new HttpRequestImpl("CONNECT", address, proxyHeaders);
    71                 MultiExchange<Void> mulEx = new MultiExchange<>(null, req,
    74                 MultiExchange<Void> mulEx = new MultiExchange<>(null, req,
    72                         client, discarding(), null, null);
    75                         client, discarding(), null, null);
    73                 Exchange<Void> connectExchange = new Exchange<>(req, mulEx);
    76                 Exchange<Void> connectExchange = mulEx.getExchange();
    74 
    77 
    75                 return connectExchange
    78                 return connectExchange
    76                         .responseAsyncImpl(delegate)
    79                         .responseAsyncImpl(delegate)
    77                         .thenCompose((Response resp) -> {
    80                         .thenCompose((Response resp) -> {
    78                             CompletableFuture<Void> cf = new MinimalFuture<>();
    81                             CompletableFuture<Void> cf = new MinimalFuture<>();
    94                             } else {
    97                             } else {
    95                                 // get the initial/remaining bytes
    98                                 // get the initial/remaining bytes
    96                                 ByteBuffer b = ((Http1Exchange<?>)connectExchange.exchImpl).drainLeftOverBytes();
    99                                 ByteBuffer b = ((Http1Exchange<?>)connectExchange.exchImpl).drainLeftOverBytes();
    97                                 int remaining = b.remaining();
   100                                 int remaining = b.remaining();
    98                                 assert remaining == 0: "Unexpected remaining: " + remaining;
   101                                 assert remaining == 0: "Unexpected remaining: " + remaining;
    99                                 connected = true;
       
   100                                 cf.complete(null);
   102                                 cf.complete(null);
   101                             }
   103                             }
   102                             return cf;
   104                             return cf;
   103                         });
   105                         })
       
   106                         .handle((result, ex) -> {
       
   107                             if (ex == null) {
       
   108                                 return MinimalFuture.completedFuture(result);
       
   109                             } else {
       
   110                                 if (debug.on())
       
   111                                     debug.log("tunnel failed with \"%s\"", ex.toString());
       
   112                                 Throwable t = ex;
       
   113                                 if (t instanceof CompletionException)
       
   114                                     t = t.getCause();
       
   115                                 if (t instanceof HttpTimeoutException) {
       
   116                                     String msg = "proxy tunneling CONNECT request timed out";
       
   117                                     t = new HttpTimeoutException(msg);
       
   118                                     t.initCause(ex);
       
   119                                 }
       
   120                                 return MinimalFuture.<Void>failedFuture(t);
       
   121                             }
       
   122                         })
       
   123                         .thenCompose(Function.identity());
   104             });
   124             });
       
   125     }
       
   126 
       
   127     public CompletableFuture<Void> finishConnect() {
       
   128         connected = true;
       
   129         return MinimalFuture.completedFuture(null);
   105     }
   130     }
   106 
   131 
   107     @Override
   132     @Override
   108     boolean isTunnel() { return true; }
   133     boolean isTunnel() { return true; }
   109 
   134