< prev index next >

src/java.httpclient/share/classes/java/net/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  */
  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         }


 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 }


  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.security.AccessControlContext;
  34 import java.security.AccessController;

  35 import static java.net.http.HttpRedirectImpl.getRedirects;
  36 import java.util.Locale;
  37 
  38 class HttpRequestImpl extends HttpRequest {
  39 
  40     private final ImmutableHeaders userHeaders;
  41     private final HttpHeadersImpl systemHeaders;
  42     private final URI uri;
  43     private InetSocketAddress authority; // only used when URI not specified
  44     private final String method;
  45     private final HttpClientImpl client;
  46     private final HttpRedirectImpl followRedirects;
  47     private final ProxySelector proxy;
  48     final BodyProcessor requestProcessor;
  49     final boolean secure;
  50     final boolean expectContinue;
  51     private final java.net.http.HttpClient.Version version;
  52     private boolean isWebSocket;
  53     final MultiExchange exchange;
  54     private boolean receiving;
  55     private AccessControlContext acc;
  56     private final long timeval;
  57     private Stream.PushGroup<?> pushGroup;
  58 
  59     public HttpRequestImpl(HttpClientImpl client,
  60                            String method,
  61                            HttpRequestBuilderImpl builder) {
  62         this.client = client;
  63         this.method = method == null? "GET" : method;
  64         this.userHeaders = builder.headers() == null ?
  65                 new ImmutableHeaders() :
  66                 new ImmutableHeaders(builder.headers(), Utils.ALLOWED_HEADERS);
  67         this.followRedirects = getRedirects(builder.followRedirects() == null ?
  68                 client.followRedirects() : builder.followRedirects());
  69         this.systemHeaders = new HttpHeadersImpl();
  70         this.uri = builder.uri();
  71         this.proxy = builder.proxy();
  72         this.expectContinue = builder.expectContinue();
  73         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
  74         this.version = builder.version();
  75         if (builder.body() == null) {
  76             this.requestProcessor = HttpRequest.noBody();
  77         } else {
  78             this.requestProcessor = builder.body();
  79         }
  80         this.exchange = new MultiExchange(this);
  81         this.timeval = builder.timeval();
  82     }
  83 
  84     /** Creates a HttpRequestImpl using fields of an existing request impl. */
  85     public HttpRequestImpl(URI uri,
  86                            HttpRequest request,
  87                            HttpClientImpl client,
  88                            String method,
  89                            HttpRequestImpl other) {
  90         this.client = client;
  91         this.method = method == null? "GET" : method;
  92         this.userHeaders = other.userHeaders;


  93         this.followRedirects = getRedirects(other.followRedirects() == null ?
  94                 client.followRedirects() : other.followRedirects());
  95         this.systemHeaders = other.systemHeaders;
  96         this.uri = uri;
  97         this.expectContinue = other.expectContinue;
  98         this.secure = other.secure;
  99         this.requestProcessor = other.requestProcessor;
 100         this.proxy = other.proxy;
 101         this.version = other.version;
 102         this.acc = other.acc;
 103         this.exchange = new MultiExchange(this);
 104         this.timeval = other.timeval;
 105     }
 106 
 107     /* used for creating CONNECT requests  */
 108     HttpRequestImpl(HttpClientImpl client,
 109                     String method,
 110                     InetSocketAddress authority) {
 111         this.client = client;
 112         this.method = method;
 113         this.followRedirects = getRedirects(client.followRedirects());
 114         this.systemHeaders = new HttpHeadersImpl();
 115         this.userHeaders = new ImmutableHeaders();
 116         this.uri = null;
 117         this.proxy = null;
 118         this.requestProcessor = HttpRequest.noBody();
 119         this.version = java.net.http.HttpClient.Version.HTTP_1_1;
 120         this.authority = authority;
 121         this.secure = false;
 122         this.expectContinue = false;
 123         this.exchange = new MultiExchange(this);
 124         this.timeval = 0; // block TODO: fix
 125     }
 126 
 127     @Override
 128     public HttpClientImpl client() {
 129         return client;
 130     }
 131 
 132     /**
 133      * Creates a HttpRequestImpl from the given set of Headers and the associated
 134      * "parent" request. Fields not taken from the headers are taken from the
 135      * parent.
 136      *
 137      * @param parent
 138      * @param headers
 139      * @return
 140      * @throws IOException
 141      */
 142     static HttpRequestImpl createPushRequest(HttpRequestImpl parent, HttpHeadersImpl headers) throws IOException {
 143         return new HttpRequestImpl(parent, headers);
 144     }
 145 
 146     // only used for push requests
 147     private HttpRequestImpl(HttpRequestImpl parent, HttpHeadersImpl headers) throws IOException {
 148         this.method = headers.firstValue(":method")
 149                 .orElseThrow(() -> new IOException("No method in Push Promise"));
 150         String path = headers.firstValue(":path")
 151                 .orElseThrow(() -> new IOException("No path in Push Promise"));
 152         String scheme = headers.firstValue(":scheme")
 153                 .orElseThrow(() -> new IOException("No scheme in Push Promise"));
 154         String authority = headers.firstValue(":authority")
 155                 .orElseThrow(() -> new IOException("No authority in Push Promise"));
 156         StringBuilder sb = new StringBuilder();
 157         sb.append(scheme).append("://").append(authority).append(path);
 158         this.uri = URI.create(sb.toString());
 159 
 160         this.client = parent.client;
 161         this.userHeaders = new ImmutableHeaders(headers, Utils.ALLOWED_HEADERS);
 162         this.followRedirects = parent.followRedirects;
 163         this.systemHeaders = parent.systemHeaders;
 164         this.expectContinue = parent.expectContinue;
 165         this.secure = parent.secure;
 166         this.requestProcessor = parent.requestProcessor;
 167         this.proxy = parent.proxy;
 168         this.version = parent.version;
 169         this.acc = parent.acc;
 170         this.exchange = parent.exchange;
 171         this.timeval = parent.timeval;
 172     }
 173 
 174     @Override
 175     public String toString() {
 176         return (uri == null ? "" : uri.toString()) + " " + method;

 177     }
 178 
 179     @Override
 180     public HttpHeaders headers() {

 181         return userHeaders;
 182     }
 183 
 184     InetSocketAddress authority() { return authority; }
 185 
 186     void setH2Upgrade() {
 187         Http2ClientImpl h2client = client.client2();
 188         systemHeaders.setHeader("Connection", "Upgrade, HTTP2-Settings");
 189         systemHeaders.setHeader("Upgrade", "h2c");
 190         systemHeaders.setHeader("HTTP2-Settings", h2client.getSettingsString());
 191     }
 192 















 193     private synchronized void receiving() {
 194         if (receiving) {
 195             throw new IllegalStateException("already receiving response");
 196         }
 197         receiving = true;
 198     }
 199 
 200     synchronized Stream.PushGroup<?> pushGroup() {
 201         return pushGroup;
 202     }
 203 
 204     /*
 205      * Response filters may result in a new HttpRequestImpl being created
 206      * (but still associated with the same API HttpRequest) and the process
 207      * is repeated.
 208      */
 209     @Override
 210     public HttpResponse response() throws IOException, InterruptedException {
 211         receiving(); // TODO: update docs
 212         if (System.getSecurityManager() != null) {
 213             acc = AccessController.getContext();
 214         }
 215         return exchange.response();
 216     }
 217 
 218     @Override
 219     public synchronized CompletableFuture<HttpResponse> responseAsync() {
 220         receiving(); // TODO: update docs
 221         if (System.getSecurityManager() != null) {
 222             acc = AccessController.getContext();
 223         }
 224         return exchange.responseAsync(null)
 225             .thenApply((r) -> (HttpResponse)r);
 226     }
 227 
 228 
 229     @SuppressWarnings("unchecked")
 230     @Override
 231     public synchronized <U> CompletableFuture<U>
 232     multiResponseAsync(MultiProcessor<U> rspproc) {
 233         if (System.getSecurityManager() != null) {
 234             acc = AccessController.getContext();
 235         }
 236         this.pushGroup = new Stream.PushGroup<>(rspproc, this);
 237         CompletableFuture<HttpResponse> cf = pushGroup.mainResponse();
 238         responseAsync()
 239             .whenComplete((HttpResponse r, Throwable t) -> {
 240                 if (r != null)
 241                     cf.complete(r);
 242                 else
 243                     cf.completeExceptionally(t);
 244                 pushGroup.pushError(t);
 245             });
 246         return (CompletableFuture<U>)pushGroup.groupResult();
 247     }
 248 
 249     @Override
 250     public boolean expectContinue() { return expectContinue; }
 251 
 252     public boolean requestHttp2() {
 253         return version.equals(HttpClient.Version.HTTP_2);
 254         //return client.getHttp2Allowed();
 255     }
 256 
 257     AccessControlContext getAccessControlContext() { return acc; }
 258 
 259     InetSocketAddress proxy() {
 260         ProxySelector ps = this.proxy;
 261         if (ps == null) {
 262             ps = client.proxy().orElse(null);
 263         }
 264         if (ps == null || method.equalsIgnoreCase("CONNECT")) {
 265             return null;
 266         }


 278     }
 279 
 280     /** Returns the follow-redirects setting for this request. */
 281     @Override
 282     public java.net.http.HttpClient.Redirect followRedirects() {
 283         return getRedirects(followRedirects);
 284     }
 285 
 286     HttpRedirectImpl followRedirectsImpl() { return followRedirects; }
 287 
 288     /**
 289      * Returns the request method for this request. If not set explicitly,
 290      * the default method for any request is "GET".
 291      */
 292     @Override
 293     public String method() { return method; }
 294 
 295     @Override
 296     public URI uri() { return uri; }
 297 
 298     HttpHeaders getUserHeaders() { return userHeaders; }
 299 
 300     HttpHeadersImpl getSystemHeaders() { return systemHeaders; }
 301 
 302     HttpClientImpl getClient() { return client; }
 303 
 304     BodyProcessor requestProcessor() { return requestProcessor; }
 305 
 306     @Override
 307     public Version version() { return version; }
 308 
 309     void addSystemHeader(String name, String value) {
 310         systemHeaders.addHeader(name, value);
 311     }
 312 
 313     void setSystemHeader(String name, String value) {
 314         systemHeaders.setHeader(name, value);
 315     }
 316 
 317     long timeval() { return timeval; }







 318 }
< prev index next >