< prev index next >

src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/HttpRequestImpl.java

Print this page




  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 jdk.incubator.http.internal.common.HttpHeadersImpl;
  29 import jdk.incubator.http.internal.websocket.WebSocketRequest;
  30 
  31 import java.io.IOException;
  32 import java.net.InetSocketAddress;

  33 import java.net.ProxySelector;
  34 import java.net.URI;
  35 import java.security.AccessControlContext;


  36 import java.time.Duration;

  37 import java.util.Locale;
  38 import java.util.Optional;
  39 
  40 import static jdk.incubator.http.internal.common.Utils.ALLOWED_HEADERS;
  41 
  42 class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
  43 
  44     private final HttpHeaders userHeaders;
  45     private final HttpHeadersImpl systemHeaders;
  46     private final URI uri;

  47     private InetSocketAddress authority; // only used when URI not specified
  48     private final String method;
  49     final BodyProcessor requestProcessor;
  50     final boolean secure;
  51     final boolean expectContinue;
  52     private boolean isWebSocket;
  53     private AccessControlContext acc;
  54     private final Duration duration;
  55     private final Optional<HttpClient.Version> version;
  56 
  57     /**
  58      * Creates an HttpRequestImpl from the given builder.
  59      */
  60     public HttpRequestImpl(HttpRequestBuilderImpl builder) {
  61         String method = builder.method();
  62         this.method = method == null? "GET" : method;
  63         this.userHeaders = ImmutableHeaders.of(builder.headers().map(), ALLOWED_HEADERS);
  64         this.systemHeaders = new HttpHeadersImpl();
  65         this.uri = builder.uri();


  66         this.expectContinue = builder.expectContinue();
  67         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
  68         if (builder.body() == null) {
  69             this.requestProcessor = HttpRequest.noBody();
  70         } else {
  71             this.requestProcessor = builder.body();
  72         }
  73         this.duration = builder.duration();
  74         this.version = builder.version();
  75     }
  76 
  77     /**
  78      * Creates an HttpRequestImpl from the given request.
  79      */
  80     public HttpRequestImpl(HttpRequest request) {
  81         String method = request.method();
  82         this.method = method == null? "GET" : method;
  83         this.userHeaders = request.headers();
  84         if (request instanceof HttpRequestImpl) {
  85             this.systemHeaders = ((HttpRequestImpl) request).systemHeaders;
  86             this.isWebSocket = ((HttpRequestImpl) request).isWebSocket;
  87         } else {
  88             this.systemHeaders = new HttpHeadersImpl();
  89         }
  90         this.uri = request.uri();









  91         this.expectContinue = request.expectContinue();
  92         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
  93         if (!request.bodyProcessor().isPresent()) {
  94             this.requestProcessor = HttpRequest.noBody();
  95         } else {
  96             this.requestProcessor = request.bodyProcessor().get();
  97         }
  98         this.duration = request.duration();
  99         this.version = request.version();
 100     }
 101 
 102     /** Creates a HttpRequestImpl using fields of an existing request impl. */
 103     public HttpRequestImpl(URI uri,
 104                            String method,
 105                            HttpRequestImpl other) {
 106         this.method = method == null? "GET" : method;
 107         this.userHeaders = other.userHeaders;
 108         this.isWebSocket = other.isWebSocket;
 109         this.systemHeaders = other.systemHeaders;
 110         this.uri = uri;

 111         this.expectContinue = other.expectContinue;
 112         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
 113         this.requestProcessor = other.requestProcessor;
 114         this.acc = other.acc;
 115         this.duration = other.duration;
 116         this.version = other.version();
 117     }
 118 
 119     /* used for creating CONNECT requests  */
 120     HttpRequestImpl(String method, HttpClientImpl client,
 121                     InetSocketAddress authority) {
 122         // TODO: isWebSocket flag is not specified, but the assumption is that
 123         // such a request will never be made on a connection that will be returned
 124         // to the connection pool (we might need to revisit this constructor later)
 125         this.method = method;
 126         this.systemHeaders = new HttpHeadersImpl();
 127         this.userHeaders = ImmutableHeaders.empty();
 128         this.uri = URI.create("socket://" + authority.getHostString() + ":" + Integer.toString(authority.getPort()) + "/");
 129         this.requestProcessor = HttpRequest.noBody();


 130         this.authority = authority;
 131         this.secure = false;
 132         this.expectContinue = false;
 133         this.duration = null;
 134         this.version = Optional.of(client.version());






 135     }
 136 
 137     /**
 138      * Creates a HttpRequestImpl from the given set of Headers and the associated
 139      * "parent" request. Fields not taken from the headers are taken from the
 140      * parent.
 141      */
 142     static HttpRequestImpl createPushRequest(HttpRequestImpl parent,
 143                                              HttpHeadersImpl headers)
 144         throws IOException
 145     {
 146         return new HttpRequestImpl(parent, headers);
 147     }
 148 
 149     // only used for push requests
 150     private HttpRequestImpl(HttpRequestImpl parent, HttpHeadersImpl headers)
 151         throws IOException
 152     {
 153         this.method = headers.firstValue(":method")
 154                 .orElseThrow(() -> new IOException("No method in Push Promise"));
 155         String path = headers.firstValue(":path")
 156                 .orElseThrow(() -> new IOException("No path in Push Promise"));
 157         String scheme = headers.firstValue(":scheme")
 158                 .orElseThrow(() -> new IOException("No scheme in Push Promise"));
 159         String authority = headers.firstValue(":authority")
 160                 .orElseThrow(() -> new IOException("No authority in Push Promise"));
 161         StringBuilder sb = new StringBuilder();
 162         sb.append(scheme).append("://").append(authority).append(path);
 163         this.uri = URI.create(sb.toString());
 164 
 165         this.userHeaders = ImmutableHeaders.of(headers.map(), ALLOWED_HEADERS);
 166         this.systemHeaders = parent.systemHeaders;
 167         this.expectContinue = parent.expectContinue;
 168         this.secure = parent.secure;
 169         this.requestProcessor = parent.requestProcessor;
 170         this.acc = parent.acc;
 171         this.duration = parent.duration;
 172         this.version = parent.version;
 173     }
 174 
 175     @Override
 176     public String toString() {
 177         return (uri == null ? "" : uri.toString()) + " " + method;
 178     }
 179 
 180     @Override
 181     public HttpHeaders headers() {
 182         return userHeaders;
 183     }
 184 
 185     InetSocketAddress authority() { return authority; }
 186 
 187     void setH2Upgrade(Http2ClientImpl h2client) {
 188         systemHeaders.setHeader("Connection", "Upgrade, HTTP2-Settings");
 189         systemHeaders.setHeader("Upgrade", "h2c");
 190         systemHeaders.setHeader("HTTP2-Settings", h2client.getSettingsString());
 191     }
 192 
 193     @Override
 194     public boolean expectContinue() { return expectContinue; }
 195 
 196     InetSocketAddress proxy(HttpClientImpl client) {
 197         ProxySelector ps = client.proxy().orElse(null);
 198         if (ps == null) {
 199             ps = client.proxy().orElse(null);






 200         }
 201         if (ps == null || method.equalsIgnoreCase("CONNECT")) {



 202             return null;
 203         }
 204         return (InetSocketAddress)ps.select(uri).get(0).address();
 205     }
 206 
 207     boolean secure() { return secure; }
 208 
 209     @Override






 210     public void isWebSocket(boolean is) {
 211         isWebSocket = is;
 212     }
 213 
 214     boolean isWebSocket() {
 215         return isWebSocket;
 216     }
 217 
 218 //    /** Returns the follow-redirects setting for this request. */
 219 //    @Override
 220 //    public jdk.incubator.http.HttpClient.Redirect followRedirects() {
 221 //        return followRedirects;
 222 //    }
 223 
 224     @Override
 225     public Optional<BodyProcessor> bodyProcessor() {
 226         return Optional.of(requestProcessor);

 227     }
 228 
 229     /**
 230      * Returns the request method for this request. If not set explicitly,
 231      * the default method for any request is "GET".
 232      */
 233     @Override
 234     public String method() { return method; }
 235 
 236     @Override
 237     public URI uri() { return uri; }
 238 
 239     @Override
 240     public Duration duration() {
 241         return duration;
 242     }
 243 
 244 //    HttpClientImpl client() {
 245 //        return client;
 246 //    }
 247 
 248     HttpHeaders getUserHeaders() { return userHeaders; }
 249 
 250     HttpHeadersImpl getSystemHeaders() { return systemHeaders; }
 251 
 252     @Override
 253     public Optional<HttpClient.Version> version() { return version; }
 254 
 255     void addSystemHeader(String name, String value) {
 256         systemHeaders.addHeader(name, value);
 257     }
 258 
 259     @Override
 260     public void setSystemHeader(String name, String value) {
 261         systemHeaders.setHeader(name, value);
 262     }
 263 
 264 //    @Override
 265 //    public <T> HttpResponse<T>
 266 //    response(HttpResponse.BodyHandler<T> responseHandler)
 267 //        throws IOException, InterruptedException
 268 //    {
 269 //        if (!sent.compareAndSet(false, true)) {
 270 //            throw new IllegalStateException("request already sent");
 271 //        }
 272 //        MultiExchange<Void,T> mex = new MultiExchange<>(this, responseHandler);
 273 //        return mex.response();
 274 //    }
 275 //
 276 //    @Override
 277 //    public <T> CompletableFuture<HttpResponse<T>>
 278 //    responseAsync(HttpResponse.BodyHandler<T> responseHandler)
 279 //    {
 280 //        if (!sent.compareAndSet(false, true)) {
 281 //            throw new IllegalStateException("request already sent");
 282 //        }
 283 //        MultiExchange<Void,T> mex = new MultiExchange<>(this, responseHandler);
 284 //        return mex.responseAsync(null)
 285 //                  .thenApply((HttpResponseImpl<T> b) -> (HttpResponse<T>) b);
 286 //    }
 287 //
 288 //    @Override
 289 //    public <U, T> CompletableFuture<U>
 290 //    multiResponseAsync(HttpResponse.MultiProcessor<U, T> responseHandler)
 291 //    {
 292 //        if (!sent.compareAndSet(false, true)) {
 293 //            throw new IllegalStateException("request already sent");
 294 //        }
 295 //        MultiExchange<U,T> mex = new MultiExchange<>(this, responseHandler);
 296 //        return mex.multiResponseAsync();
 297 //    }
 298 
 299     public InetSocketAddress getAddress(HttpClientImpl client) {
 300         URI uri = uri();
 301         if (uri == null) {
 302             return authority();
 303         }
 304         int port = uri.getPort();
 305         if (port == -1) {
 306             if (uri.getScheme().equalsIgnoreCase("https")) {
 307                 port = 443;
 308             } else {
 309                 port = 80;
 310             }
 311         }
 312         String host = uri.getHost();
 313         if (proxy(client) == null) {
 314             return new InetSocketAddress(host, port);


 315         } else {
 316             return InetSocketAddress.createUnresolved(host, port);
 317         }
 318     }
 319 }


  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 jdk.incubator.http.internal.common.HttpHeadersImpl;
  29 import jdk.incubator.http.internal.websocket.WebSocketRequest;
  30 
  31 import java.io.IOException;
  32 import java.net.InetSocketAddress;
  33 import java.net.Proxy;
  34 import java.net.ProxySelector;
  35 import java.net.URI;
  36 import java.security.AccessControlContext;
  37 import java.security.AccessController;
  38 import java.security.PrivilegedAction;
  39 import java.time.Duration;
  40 import java.util.List;
  41 import java.util.Locale;
  42 import java.util.Optional;
  43 
  44 import static jdk.incubator.http.internal.common.Utils.ALLOWED_HEADERS;
  45 
  46 class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
  47 
  48     private final HttpHeaders userHeaders;
  49     private final HttpHeadersImpl systemHeaders;
  50     private final URI uri;
  51     private Proxy proxy;
  52     private InetSocketAddress authority; // only used when URI not specified
  53     private final String method;
  54     final BodyPublisher requestPublisher;
  55     final boolean secure;
  56     final boolean expectContinue;
  57     private boolean isWebSocket;
  58     private AccessControlContext acc;
  59     private final Duration timeout;  // may be null
  60     private final Optional<HttpClient.Version> version;
  61 
  62     /**
  63      * Creates an HttpRequestImpl from the given builder.
  64      */
  65     public HttpRequestImpl(HttpRequestBuilderImpl builder) {
  66         String method = builder.method();
  67         this.method = method == null ? "GET" : method;
  68         this.userHeaders = ImmutableHeaders.of(builder.headers().map(), ALLOWED_HEADERS);
  69         this.systemHeaders = new HttpHeadersImpl();
  70         this.uri = builder.uri();
  71         assert uri != null;
  72         this.proxy = null;
  73         this.expectContinue = builder.expectContinue();
  74         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
  75         this.requestPublisher = builder.bodyPublisher();  // may be null
  76         this.timeout = builder.timeout();




  77         this.version = builder.version();
  78     }
  79 
  80     /**
  81      * Creates an HttpRequestImpl from the given request.
  82      */
  83     public HttpRequestImpl(HttpRequest request, ProxySelector ps, AccessControlContext acc) {
  84         String method = request.method();
  85         this.method = method == null ? "GET" : method;
  86         this.userHeaders = request.headers();
  87         if (request instanceof HttpRequestImpl) {
  88             this.systemHeaders = ((HttpRequestImpl) request).systemHeaders;
  89             this.isWebSocket = ((HttpRequestImpl) request).isWebSocket;
  90         } else {
  91             this.systemHeaders = new HttpHeadersImpl();
  92         }
  93         this.uri = request.uri();
  94         if (isWebSocket) {
  95             // WebSocket determines and sets the proxy itself
  96             this.proxy = ((HttpRequestImpl) request).proxy;
  97         } else {
  98             if (ps != null)
  99                 this.proxy = retrieveProxy(ps, uri);
 100             else
 101                 this.proxy = null;
 102         }
 103         this.expectContinue = request.expectContinue();
 104         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
 105         this.requestPublisher = request.bodyPublisher().orElse(null);
 106         if (acc != null && requestPublisher instanceof RequestPublishers.FilePublisher) {
 107             // Restricts the file publisher with the senders ACC, if any
 108             ((RequestPublishers.FilePublisher)requestPublisher).setAccessControlContext(acc);
 109         }
 110         this.timeout = request.timeout().orElse(null);
 111         this.version = request.version();
 112     }
 113 
 114     /** Creates a HttpRequestImpl using fields of an existing request impl. */
 115     public HttpRequestImpl(URI uri,
 116                            String method,
 117                            HttpRequestImpl other) {
 118         this.method = method == null? "GET" : method;
 119         this.userHeaders = other.userHeaders;
 120         this.isWebSocket = other.isWebSocket;
 121         this.systemHeaders = other.systemHeaders;
 122         this.uri = uri;
 123         this.proxy = other.proxy;
 124         this.expectContinue = other.expectContinue;
 125         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
 126         this.requestPublisher = other.requestPublisher;  // may be null
 127         this.acc = other.acc;
 128         this.timeout = other.timeout;
 129         this.version = other.version();
 130     }
 131 
 132     /* used for creating CONNECT requests  */
 133     HttpRequestImpl(String method, InetSocketAddress authority) {

 134         // TODO: isWebSocket flag is not specified, but the assumption is that
 135         // such a request will never be made on a connection that will be returned
 136         // to the connection pool (we might need to revisit this constructor later)
 137         this.method = method;
 138         this.systemHeaders = new HttpHeadersImpl();
 139         this.userHeaders = ImmutableHeaders.empty();
 140         this.uri = URI.create("socket://" + authority.getHostString() + ":"
 141                               + Integer.toString(authority.getPort()) + "/");
 142         this.proxy = null;
 143         this.requestPublisher = null;
 144         this.authority = authority;
 145         this.secure = false;
 146         this.expectContinue = false;
 147         this.timeout = null;
 148         // The CONNECT request sent for tunneling is only used in two cases:
 149         //   1. websocket, which only supports HTTP/1.1
 150         //   2. SSL tunneling through a HTTP/1.1 proxy
 151         // In either case we do not want to upgrade the connection to the proxy.
 152         // What we want to possibly upgrade is the tunneled connection to the
 153         // target server (so not the CONNECT request itself)
 154         this.version = Optional.of(HttpClient.Version.HTTP_1_1);
 155     }
 156 
 157     /**
 158      * Creates a HttpRequestImpl from the given set of Headers and the associated
 159      * "parent" request. Fields not taken from the headers are taken from the
 160      * parent.
 161      */
 162     static HttpRequestImpl createPushRequest(HttpRequestImpl parent,
 163                                              HttpHeadersImpl headers)
 164         throws IOException
 165     {
 166         return new HttpRequestImpl(parent, headers);
 167     }
 168 
 169     // only used for push requests
 170     private HttpRequestImpl(HttpRequestImpl parent, HttpHeadersImpl headers)
 171         throws IOException
 172     {
 173         this.method = headers.firstValue(":method")
 174                 .orElseThrow(() -> new IOException("No method in Push Promise"));
 175         String path = headers.firstValue(":path")
 176                 .orElseThrow(() -> new IOException("No path in Push Promise"));
 177         String scheme = headers.firstValue(":scheme")
 178                 .orElseThrow(() -> new IOException("No scheme in Push Promise"));
 179         String authority = headers.firstValue(":authority")
 180                 .orElseThrow(() -> new IOException("No authority in Push Promise"));
 181         StringBuilder sb = new StringBuilder();
 182         sb.append(scheme).append("://").append(authority).append(path);
 183         this.uri = URI.create(sb.toString());
 184         this.proxy = null;
 185         this.userHeaders = ImmutableHeaders.of(headers.map(), ALLOWED_HEADERS);
 186         this.systemHeaders = parent.systemHeaders;
 187         this.expectContinue = parent.expectContinue;
 188         this.secure = parent.secure;
 189         this.requestPublisher = parent.requestPublisher;
 190         this.acc = parent.acc;
 191         this.timeout = parent.timeout;
 192         this.version = parent.version;
 193     }
 194 
 195     @Override
 196     public String toString() {
 197         return (uri == null ? "" : uri.toString()) + " " + method;
 198     }
 199 
 200     @Override
 201     public HttpHeaders headers() {
 202         return userHeaders;
 203     }
 204 
 205     InetSocketAddress authority() { return authority; }
 206 
 207     void setH2Upgrade(Http2ClientImpl h2client) {
 208         systemHeaders.setHeader("Connection", "Upgrade, HTTP2-Settings");
 209         systemHeaders.setHeader("Upgrade", "h2c");
 210         systemHeaders.setHeader("HTTP2-Settings", h2client.getSettingsString());
 211     }
 212 
 213     @Override
 214     public boolean expectContinue() { return expectContinue; }
 215 
 216     /** Retrieves the proxy, from the given ProxySelector, if there is one. */
 217     private static Proxy retrieveProxy(ProxySelector ps, URI uri) {
 218         Proxy proxy = null;
 219         List<Proxy> pl = ps.select(uri);
 220         if (!pl.isEmpty()) {
 221             Proxy p = pl.get(0);
 222             if (p.type() == Proxy.Type.HTTP)
 223                 proxy = p;
 224         }
 225         return proxy;
 226     }
 227 
 228     InetSocketAddress proxy() {
 229         if (proxy == null || proxy.type() != Proxy.Type.HTTP
 230                 || method.equalsIgnoreCase("CONNECT")) {
 231             return null;
 232         }
 233         return (InetSocketAddress)proxy.address();
 234     }
 235 
 236     boolean secure() { return secure; }
 237 
 238     @Override
 239     public void setProxy(Proxy proxy) {
 240         assert isWebSocket;
 241         this.proxy = proxy;
 242     }
 243 
 244     @Override
 245     public void isWebSocket(boolean is) {
 246         isWebSocket = is;
 247     }
 248 
 249     boolean isWebSocket() {
 250         return isWebSocket;
 251     }
 252 






 253     @Override
 254     public Optional<BodyPublisher> bodyPublisher() {
 255         return requestPublisher == null ? Optional.empty()
 256                                         : Optional.of(requestPublisher);
 257     }
 258 
 259     /**
 260      * Returns the request method for this request. If not set explicitly,
 261      * the default method for any request is "GET".
 262      */
 263     @Override
 264     public String method() { return method; }
 265 
 266     @Override
 267     public URI uri() { return uri; }
 268 
 269     @Override
 270     public Optional<Duration> timeout() {
 271         return timeout == null ? Optional.empty() : Optional.of(timeout);
 272     }
 273 




 274     HttpHeaders getUserHeaders() { return userHeaders; }
 275 
 276     HttpHeadersImpl getSystemHeaders() { return systemHeaders; }
 277 
 278     @Override
 279     public Optional<HttpClient.Version> version() { return version; }
 280 
 281     void addSystemHeader(String name, String value) {
 282         systemHeaders.addHeader(name, value);
 283     }
 284 
 285     @Override
 286     public void setSystemHeader(String name, String value) {
 287         systemHeaders.setHeader(name, value);
 288     }
 289 
 290     InetSocketAddress getAddress() {



































 291         URI uri = uri();
 292         if (uri == null) {
 293             return authority();
 294         }
 295         int p = uri.getPort();
 296         if (p == -1) {
 297             if (uri.getScheme().equalsIgnoreCase("https")) {
 298                 p = 443;
 299             } else {
 300                 p = 80;
 301             }
 302         }
 303         final String host = uri.getHost();
 304         final int port = p;
 305         if (proxy() == null) {
 306             PrivilegedAction<InetSocketAddress> pa = () -> new InetSocketAddress(host, port);
 307             return AccessController.doPrivileged(pa);
 308         } else {
 309             return InetSocketAddress.createUnresolved(host, port);
 310         }
 311     }
 312 }
< prev index next >