< prev index next >
   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  */
  24 package java.net.http;
  25 
  26 import java.io.IOException;
  27 import java.net.InetSocketAddress;
  28 import java.net.ProxySelector;
  29 import java.net.URI;
  30 import java.net.http.HttpClient.Version;
  31 import java.net.http.HttpResponse.MultiProcessor;
  32 import java.util.concurrent.CompletableFuture;
  33 import java.net.SocketPermission;
  34 import java.security.AccessControlContext;
  35 import java.security.AccessController;
  36 import java.util.Set;
  37 import static java.net.http.HttpRedirectImpl.getRedirects;
  38 import java.util.Locale;
  39 
  40 class HttpRequestImpl extends HttpRequest {
  41 
  42     private final HttpHeadersImpl userHeaders;
  43     private final HttpHeadersImpl systemHeaders;
  44     private final URI uri;
  45     private InetSocketAddress authority; // only used when URI not specified
  46     private final String method;
  47     private final HttpClientImpl client;
  48     private final HttpRedirectImpl followRedirects;
  49     private final ProxySelector proxy;
  50     final BodyProcessor requestProcessor;
  51     final boolean secure;
  52     final boolean expectContinue;
  53     private final java.net.http.HttpClient.Version version;
  54     private boolean isWebSocket;
  55     final MultiExchange exchange;
  56     private boolean receiving;
  57     private AccessControlContext acc;
  58     private final long timeval;
  59 
  60     public HttpRequestImpl(HttpClientImpl client,
  61                            String method,
  62                            HttpRequestBuilderImpl builder) {
  63         this.client = client;
  64         this.method = method == null? "GET" : method;
  65         this.userHeaders = builder.headers() == null ?
  66                 new HttpHeadersImpl() : builder.headers();
  67         dropDisallowedHeaders();
  68         this.followRedirects = getRedirects(builder.followRedirects() == null ?
  69                 client.followRedirects() : builder.followRedirects());
  70         this.systemHeaders = new HttpHeadersImpl();
  71         this.uri = builder.uri();
  72         this.proxy = builder.proxy();
  73         this.expectContinue = builder.expectContinue();
  74         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
  75         this.version = builder.version();
  76         if (builder.body() == null) {
  77             this.requestProcessor = HttpRequest.noBody();
  78         } else {
  79             this.requestProcessor = builder.body();
  80         }
  81         this.exchange = new MultiExchange(this);
  82         this.timeval = builder.timeval();
  83     }
  84 
  85     /** Creates a HttpRequestImpl using fields of an existing request impl. */
  86     public HttpRequestImpl(URI uri,
  87                            HttpRequest request,
  88                            HttpClientImpl client,
  89                            String method,
  90                            HttpRequestImpl other) {
  91         this.client = client;
  92         this.method = method == null? "GET" : method;
  93         this.userHeaders = other.userHeaders == null ?
  94                 new HttpHeadersImpl() : other.userHeaders;
  95         dropDisallowedHeaders();
  96         this.followRedirects = getRedirects(other.followRedirects() == null ?
  97                 client.followRedirects() : other.followRedirects());
  98         this.systemHeaders = other.systemHeaders;
  99         this.uri = uri;
 100         this.expectContinue = other.expectContinue;
 101         this.secure = other.secure;
 102         this.requestProcessor = other.requestProcessor;
 103         this.proxy = other.proxy;
 104         this.version = other.version;
 105         this.acc = other.acc;
 106         this.exchange = new MultiExchange(this);
 107         this.timeval = other.timeval;
 108     }
 109 
 110     /* used for creating CONNECT requests  */
 111     HttpRequestImpl(HttpClientImpl client,
 112                     String method,
 113                     InetSocketAddress authority) {
 114         this.client = client;
 115         this.method = method;
 116         this.followRedirects = getRedirects(client.followRedirects());
 117         this.systemHeaders = new HttpHeadersImpl();
 118         this.userHeaders = new HttpHeadersImpl();
 119         this.uri = null;
 120         this.proxy = null;
 121         this.requestProcessor = HttpRequest.noBody();
 122         this.version = java.net.http.HttpClient.Version.HTTP_1_1;
 123         this.authority = authority;
 124         this.secure = false;
 125         this.expectContinue = false;
 126         this.exchange = new MultiExchange(this);
 127         this.timeval = 0; // block TODO: fix
 128     }
 129 
 130     @Override
 131     public HttpClientImpl client() {
 132         return client;
 133     }
 134 
 135 
 136     @Override
 137     public String toString() {
 138         return (uri == null ? "" : uri.toString()) + "/" + method + "("
 139                 + hashCode() + ")";
 140     }
 141 
 142     @Override
 143     public HttpHeaders headers() {
 144         userHeaders.makeUnmodifiable();
 145         return userHeaders;
 146     }
 147 
 148     InetSocketAddress authority() { return authority; }
 149 
 150     void setH2Upgrade() {
 151         Http2ClientImpl h2client = client.client2();
 152         systemHeaders.setHeader("Connection", "Upgrade, HTTP2-Settings");
 153         systemHeaders.setHeader("Upgrade", "h2c");
 154         systemHeaders.setHeader("HTTP2-Settings", h2client.getSettingsString());
 155     }
 156 
 157     private static final Set<String>  DISALLOWED_HEADERS_SET = Set.of(
 158         "authorization", "connection", "cookie", "content-length",
 159         "date", "expect", "from", "host", "origin", "proxy-authorization",
 160         "referer", "user-agent", "upgrade", "via", "warning");
 161 
 162 
 163     // we silently drop headers that are disallowed
 164     private void dropDisallowedHeaders() {
 165         Set<String> hdrnames = userHeaders.directMap().keySet();
 166 
 167         hdrnames.removeIf((s) ->
 168               DISALLOWED_HEADERS_SET.contains(s.toLowerCase())
 169         );
 170     }
 171 
 172     private synchronized void receiving() {
 173         if (receiving) {
 174             throw new IllegalStateException("already receiving response");
 175         }
 176         receiving = true;
 177     }
 178 
 179     /*
 180      * Response filters may result in a new HttpRequestImpl being created
 181      * (but still associated with the same API HttpRequest) and the process
 182      * is repeated.
 183      */
 184     @Override
 185     public HttpResponse response() throws IOException, InterruptedException {
 186         receiving(); // TODO: update docs
 187         if (System.getSecurityManager() != null) {
 188             acc = AccessController.getContext();
 189         }
 190         return exchange.response();
 191     }
 192 
 193     @Override
 194     public synchronized CompletableFuture<HttpResponse> responseAsync() {
 195         receiving(); // TODO: update docs
 196         if (System.getSecurityManager() != null) {
 197             acc = AccessController.getContext();
 198         }
 199         return exchange.responseAsync(null)
 200             .thenApply((r) -> (HttpResponse)r);
 201     }
 202 
 203     public <U> CompletableFuture<U>
 204     sendAsyncMulti(HttpResponse.MultiProcessor<U> rspproc) {
 205         // To change body of generated methods, choose Tools | Templates.
 206         throw new UnsupportedOperationException("Not supported yet.");
 207     }
 208 
 209     @Override
 210     public boolean expectContinue() { return expectContinue; }
 211 
 212     public boolean requestHttp2() {
 213         return version.equals(HttpClient.Version.HTTP_2);
 214         //return client.getHttp2Allowed();
 215     }
 216 
 217     AccessControlContext getAccessControlContext() { return acc; }
 218 
 219     InetSocketAddress proxy() {
 220         ProxySelector ps = this.proxy;
 221         if (ps == null) {
 222             ps = client.proxy().orElse(null);
 223         }
 224         if (ps == null || method.equalsIgnoreCase("CONNECT")) {
 225             return null;
 226         }
 227         return (InetSocketAddress)ps.select(uri).get(0).address();
 228     }
 229 
 230     boolean secure() { return secure; }
 231 
 232     void isWebSocket(boolean is) {
 233         isWebSocket = is;
 234     }
 235 
 236     boolean isWebSocket() {
 237         return isWebSocket;
 238     }
 239 
 240     /** Returns the follow-redirects setting for this request. */
 241     @Override
 242     public java.net.http.HttpClient.Redirect followRedirects() {
 243         return getRedirects(followRedirects);
 244     }
 245 
 246     HttpRedirectImpl followRedirectsImpl() { return followRedirects; }
 247 
 248     /**
 249      * Returns the request method for this request. If not set explicitly,
 250      * the default method for any request is "GET".
 251      */
 252     @Override
 253     public String method() { return method; }
 254 
 255     @Override
 256     public URI uri() { return uri; }
 257 
 258     HttpHeadersImpl getUserHeaders() { return userHeaders; }
 259 
 260     HttpHeadersImpl getSystemHeaders() { return systemHeaders; }
 261 
 262     HttpClientImpl getClient() { return client; }
 263 
 264     BodyProcessor requestProcessor() { return requestProcessor; }
 265 
 266     @Override
 267     public Version version() { return version; }
 268 
 269     void addSystemHeader(String name, String value) {
 270         systemHeaders.addHeader(name, value);
 271     }
 272 
 273     void setSystemHeader(String name, String value) {
 274         systemHeaders.setHeader(name, value);
 275     }
 276 
 277     long timeval() { return timeval; }
 278 
 279     @Override
 280     public <U> CompletableFuture<U>
 281     multiResponseAsync(MultiProcessor<U> rspproc) {
 282         //To change body of generated methods, choose Tools | Templates.
 283         throw new UnsupportedOperationException("Not supported yet.");
 284     }
 285 }
< prev index next >