1 /* 2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.incubator.http; 27 28 import java.io.IOException; 29 import java.util.concurrent.CompletableFuture; 30 import java.util.concurrent.Executor; 31 import jdk.incubator.http.internal.common.MinimalFuture; 32 import static jdk.incubator.http.HttpClient.Version.HTTP_1_1; 33 34 /** 35 * Splits request so that headers and body can be sent separately with optional 36 * (multiple) responses in between (e.g. 100 Continue). Also request and 37 * response always sent/received in different calls. 38 * 39 * Synchronous and asynchronous versions of each method are provided. 40 * 41 * Separate implementations of this class exist for HTTP/1.1 and HTTP/2 42 * Http1Exchange (HTTP/1.1) 43 * Stream (HTTP/2) 44 * 45 * These implementation classes are where work is allocated to threads. 46 */ 47 abstract class ExchangeImpl<T> { 48 49 final Exchange<T> exchange; 50 51 ExchangeImpl(Exchange<T> e) { 52 // e == null means a http/2 pushed stream 53 this.exchange = e; 54 } 55 56 final Exchange<T> getExchange() { 57 return exchange; 58 } 59 60 61 /** 62 * Returns the {@link HttpConnection} instance to which this exchange is 63 * assigned. 64 */ 65 abstract HttpConnection connection(); 66 67 /** 68 * Initiates a new exchange and assigns it to a connection if one exists 69 * already. connection usually null. 70 */ 71 static <U> ExchangeImpl<U> get(Exchange<U> exchange, HttpConnection connection) 72 throws IOException, InterruptedException 73 { 74 HttpRequestImpl req = exchange.request(); 75 if (exchange.version() == HTTP_1_1) { 76 return new Http1Exchange<>(exchange, connection); 77 } else { 78 Http2ClientImpl c2 = exchange.client().client2(); // TODO: improve 79 HttpRequestImpl request = exchange.request(); 80 Http2Connection c; 81 try { 82 c = c2.getConnectionFor(request); 83 } catch (Http2Connection.ALPNException e) { 84 // failed to negotiate "h2" 85 AbstractAsyncSSLConnection as = e.getConnection(); 86 as.stopAsyncReading(); 87 HttpConnection sslc = as.downgrade(); 88 ExchangeImpl<U> ex = new Http1Exchange<>(exchange, sslc); 89 return ex; 90 } 91 if (c == null) { 92 // no existing connection. Send request with HTTP 1 and then 93 // upgrade if successful 94 ExchangeImpl<U> ex = new Http1Exchange<>(exchange, connection); 95 exchange.h2Upgrade(); 96 return ex; 97 } 98 return c.createStream(exchange); 99 } 100 } 101 102 /* The following methods have separate HTTP/1.1 and HTTP/2 implementations */ 103 104 /** 105 * Sends the request headers only. May block until all sent. 106 */ 107 abstract void sendHeadersOnly() throws IOException, InterruptedException; 108 109 // Blocking impl but in async style 110 111 CompletableFuture<ExchangeImpl<T>> sendHeadersAsync() { 112 // this is blocking. cf will already be completed. 113 return MinimalFuture.supply(() -> { 114 sendHeadersOnly(); 115 return this; 116 }); 117 } 118 119 /** 120 * Gets response by blocking if necessary. This may be an 121 * intermediate response (like 101) or a final response 200 etc. Returns 122 * before body is read. 123 */ 124 abstract Response getResponse() throws IOException; 125 126 abstract T readBody(HttpResponse.BodyHandler<T> handler, 127 boolean returnConnectionToPool) throws IOException; 128 129 abstract CompletableFuture<T> readBodyAsync(HttpResponse.BodyHandler<T> handler, 130 boolean returnConnectionToPool, 131 Executor executor); 132 133 /** 134 * Async version of getResponse. Completes before body is read. 135 */ 136 abstract CompletableFuture<Response> getResponseAsync(Executor executor); 137 138 /** 139 * Sends a request body after request headers. 140 */ 141 abstract void sendBody() throws IOException, InterruptedException; 142 143 // Async version of sendBody(). This only used when body sent separately 144 // to headers (100 continue) 145 CompletableFuture<ExchangeImpl<T>> sendBodyAsync() { 146 return MinimalFuture.supply(() -> { 147 sendBody(); 148 return this; 149 }); 150 } 151 152 /** 153 * Cancels a request. Not currently exposed through API. 154 */ 155 abstract void cancel(); 156 157 /** 158 * Cancels a request with a cause. Not currently exposed through API. 159 */ 160 abstract void cancel(IOException cause); 161 }