1 /* 2 * Copyright (c) 2015, 2017, 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.net.URI; 30 import java.nio.ByteBuffer; 31 import java.util.Optional; 32 import java.util.concurrent.CompletableFuture; 33 import java.util.function.Supplier; 34 import javax.net.ssl.SSLParameters; 35 import jdk.incubator.http.internal.websocket.RawChannel; 36 37 /** 38 * The implementation class for HttpResponse 39 */ 40 class HttpResponseImpl<T> extends HttpResponse<T> implements RawChannel.Provider { 41 42 final int responseCode; 43 final Exchange<T> exchange; 44 final HttpRequest initialRequest; 45 final Optional<HttpResponse<T>> previousResponse; 46 final HttpHeaders headers; 47 final SSLParameters sslParameters; 48 final URI uri; 49 final HttpClient.Version version; 50 RawChannel rawchan; 51 final HttpConnection connection; 52 final Stream<T> stream; 53 final T body; 54 55 public HttpResponseImpl(HttpRequest initialRequest, 56 Response response, 57 HttpResponse<T> previousResponse, 58 T body, 59 Exchange<T> exch) { 60 this.responseCode = response.statusCode(); 61 this.exchange = exch; 62 this.initialRequest = initialRequest; 63 this.previousResponse = Optional.ofNullable(previousResponse); 64 this.headers = response.headers(); 65 //this.trailers = trailers; 66 this.sslParameters = exch.client().sslParameters(); 67 this.uri = response.request().uri(); 68 this.version = response.version(); 69 this.connection = exch.exchImpl.connection(); 70 this.stream = null; 71 this.body = body; 72 } 73 74 // // A response to a PUSH_PROMISE 75 // public HttpResponseImpl(Response response, 76 // HttpRequestImpl pushRequest, 77 // ImmutableHeaders headers, 78 // Stream<T> stream, 79 // SSLParameters sslParameters, 80 // T body) { 81 // this.responseCode = response.statusCode(); 82 // this.exchange = null; 83 // this.initialRequest = null; // ## fix this 84 // this.finalRequest = pushRequest; 85 // this.headers = headers; 86 // //this.trailers = null; 87 // this.sslParameters = sslParameters; 88 // this.uri = finalRequest.uri(); // TODO: take from headers 89 // this.version = HttpClient.Version.HTTP_2; 90 // this.connection = stream.connection(); 91 // this.stream = stream; 92 // this.body = body; 93 // } 94 95 private ExchangeImpl<?> exchangeImpl() { 96 return exchange != null ? exchange.exchImpl : stream; 97 } 98 99 @Override 100 public int statusCode() { 101 return responseCode; 102 } 103 104 @Override 105 public HttpRequest request() { 106 return initialRequest; 107 } 108 109 @Override 110 public Optional<HttpResponse<T>> previousResponse() { 111 return previousResponse; 112 } 113 114 @Override 115 public HttpHeaders headers() { 116 return headers; 117 } 118 119 @Override 120 public T body() { 121 return body; 122 } 123 124 @Override 125 public SSLParameters sslParameters() { 126 return sslParameters; 127 } 128 129 @Override 130 public URI uri() { 131 return uri; 132 } 133 134 @Override 135 public HttpClient.Version version() { 136 return version; 137 } 138 // keepalive flag determines whether connection is closed or kept alive 139 // by reading/skipping data 140 141 /** 142 * Returns a RawChannel that may be used for WebSocket protocol. 143 * @implNote This implementation does not support RawChannel over 144 * HTTP/2 connections. 145 * @return a RawChannel that may be used for WebSocket protocol. 146 * @throws UnsupportedOperationException if getting a RawChannel over 147 * this connection is not supported. 148 * @throws IOException if an I/O exception occurs while retrieving 149 * the channel. 150 */ 151 @Override 152 public synchronized RawChannel rawChannel() throws IOException { 153 if (rawchan == null) { 154 ExchangeImpl<?> exchImpl = exchangeImpl(); 155 if (!(exchImpl instanceof Http1Exchange)) { 156 // RawChannel is only used for WebSocket - and WebSocket 157 // is not supported over HTTP/2 yet, so we should not come 158 // here. Getting a RawChannel over HTTP/2 might be supported 159 // in the future, but it would entail retrieving any left over 160 // bytes that might have been read but not consumed by the 161 // HTTP/2 connection. 162 throw new UnsupportedOperationException("RawChannel is not supported over HTTP/2"); 163 } 164 // Http1Exchange may have some remaining bytes in its 165 // internal buffer. 166 Supplier<ByteBuffer> initial = ((Http1Exchange<?>)exchImpl)::drainLeftOverBytes; 167 rawchan = new RawChannelImpl(exchange.client(), connection, initial); 168 } 169 return rawchan; 170 } 171 172 @Override 173 public String toString() { 174 StringBuilder sb = new StringBuilder(); 175 String method = request().method(); 176 URI uri = request().uri(); 177 String uristring = uri == null ? "" : uri.toString(); 178 sb.append('(') 179 .append(method) 180 .append(" ") 181 .append(uristring) 182 .append(") ") 183 .append(statusCode()); 184 return sb.toString(); 185 } 186 }