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.net.Authenticator;
  30 import java.net.CookieManager;
  31 import java.net.InetSocketAddress;
  32 import java.net.ProxySelector;
  33 import java.net.URI;
  34 import java.util.Optional;
  35 import java.util.concurrent.CompletableFuture;
  36 import java.util.concurrent.Executor;
  37 import javax.net.ssl.SSLContext;
  38 import javax.net.ssl.SSLParameters;
  39 
  40 /**
  41  * A container for configuration information common to multiple {@link
  42  * HttpRequest}s. All requests are sent through a {@code HttpClient}.
  43  * {@Incubating}
  44  *
  45  * <p> {@code HttpClient}s are immutable and created from a builder returned
  46  * from {@link HttpClient#newBuilder()}. Request builders are created by calling
  47  * {@link HttpRequest#newBuilder() }.
  48  * <p>
  49  * See {@link HttpRequest} for examples of usage of this API.
  50  *
  51  * @since 9
  52  */
  53 public abstract class HttpClient {
  54 
  55     /**
  56      * Creates an HttpClient.
  57      */
  58     protected HttpClient() {}
  59 
  60     /**
  61      * Returns a new HttpClient with default settings.
  62      *
  63      * @return a new HttpClient
  64      */
  65     public static HttpClient newHttpClient() {
  66         return new HttpClientBuilderImpl().build();
  67     }
  68 
  69     /**
  70      * Creates a new {@code HttpClient} builder.
  71      *
  72      * @return a {@code HttpClient.Builder}
  73      */
  74     public static Builder newBuilder() {
  75         return new HttpClientBuilderImpl();
  76     }
  77 
  78     /**
  79      * A builder of immutable {@link HttpClient}s. {@code HttpClient.Builder}s
  80      * are created by calling {@link HttpClient#newBuilder()}.
  81      * {@Incubating}
  82      *
  83      * <p> Each of the setter methods in this class modifies the state of the
  84      * builder and returns <i>this</i> (ie. the same instance). The methods are
  85      * not synchronized and should not be called from multiple threads without
  86      * external synchronization.
  87      *
  88      * <p> {@link #build()} returns a new {@code HttpClient} each time it is
  89      * called.
  90      *
  91      * @since 9
  92      */
  93     public abstract static class Builder {
  94 
  95         protected Builder() {}
  96 
  97         /**
  98          * Sets a cookie manager.
  99          *
 100          * @param cookieManager the cookie manager
 101          * @return this builder
 102          */
 103         public abstract Builder cookieManager(CookieManager cookieManager);
 104 
 105         /**
 106          * Sets an {@code SSLContext}. If a security manager is set, then the caller
 107          * must have the {@link java.net.NetPermission NetPermission}
 108          * ({@code "setSSLContext"})
 109          *
 110          * <p> The effect of not calling this method, is that a default {@link
 111          * javax.net.ssl.SSLContext} is used, which is normally adequate for
 112          * client applications that do not need to specify protocols, or require
 113          * client authentication.
 114          *
 115          * @param sslContext the SSLContext
 116          * @return this builder
 117          * @throws SecurityException if a security manager is set and the
 118          *                           caller does not have any required permission
 119          */
 120         public abstract Builder sslContext(SSLContext sslContext);
 121 
 122         /**
 123          * Sets an {@code SSLParameters}. If this method is not called, then a default
 124          * set of parameters are used. The contents of the given object are
 125          * copied. Some parameters which are used internally by the HTTP protocol
 126          * implementation (such as application protocol list) should not be set
 127          * by callers, as they are ignored.
 128          *
 129          * @param sslParameters the SSLParameters
 130          * @return this builder
 131          */
 132         public abstract Builder sslParameters(SSLParameters sslParameters);
 133 
 134         /**
 135          * Sets the executor to be used for asynchronous tasks. If this method is
 136          * not called, a default executor is set, which is the one returned from {@link
 137          * java.util.concurrent.Executors#newCachedThreadPool()
 138          * Executors.newCachedThreadPool}.
 139          *
 140          * @param executor the Executor
 141          * @return this builder
 142          */
 143         public abstract Builder executor(Executor executor);
 144 
 145         /**
 146          * Specifies whether requests will automatically follow redirects issued
 147          * by the server. This setting can be overridden on each request. The
 148          * default value for this setting is {@link Redirect#NEVER NEVER}
 149          *
 150          * @param policy the redirection policy
 151          * @return this builder
 152          */
 153         public abstract Builder followRedirects(Redirect policy);
 154 
 155         /**
 156          * Requests a specific HTTP protocol version where possible. If not set,
 157          * the version defaults to {@link HttpClient.Version#HTTP_2}. If
 158          * {@link HttpClient.Version#HTTP_2} is set, then each request will
 159          * attempt to upgrade to HTTP/2. If the upgrade succeeds, then the
 160          * response to this request will use HTTP/2 and all subsequent requests
 161          * and responses to the same
 162          * <a href="https://tools.ietf.org/html/rfc6454#section-4">origin server</a>
 163          * will use HTTP/2. If the upgrade fails, then the response will be
 164          * handled using HTTP/1.1
 165          *
 166          * @param version the requested HTTP protocol version
 167          * @return this builder
 168          */
 169         public abstract Builder version(HttpClient.Version version);
 170 
 171         /**
 172          * Sets the default priority for any HTTP/2 requests sent from this
 173          * client. The value provided must be between {@code 1} and {@code 256}
 174          * (inclusive).
 175          *
 176          * @param priority the priority weighting
 177          * @return this builder
 178          * @throws IllegalArgumentException if the given priority is out of range
 179          */
 180         public abstract Builder priority(int priority);
 181 
 182         /**
 183          * Sets a {@link java.net.ProxySelector} for this client. If no selector
 184          * is set, then no proxies are used. If a {@code null} parameter is
 185          * given then the system wide default proxy selector is used.
 186          *
 187          * @implNote {@link java.net.ProxySelector#of(InetSocketAddress)}
 188          * provides a {@code ProxySelector} which uses one proxy for all requests.
 189          *
 190          * @param selector the ProxySelector
 191          * @return this builder
 192          */
 193         public abstract Builder proxy(ProxySelector selector);
 194 
 195         /**
 196          * Sets an authenticator to use for HTTP authentication.
 197          *
 198          * @param a the Authenticator
 199          * @return this builder
 200          */
 201         public abstract Builder authenticator(Authenticator a);
 202 
 203         /**
 204          * Returns a {@link HttpClient} built from the current state of this
 205          * builder.
 206          *
 207          * @return this builder
 208          */
 209         public abstract HttpClient build();
 210     }
 211 
 212 
 213     /**
 214      * Returns an {@code Optional} which contains this client's {@link
 215      * CookieManager}. If no {@code CookieManager} was set in this client's builder,
 216      * then the {@code Optional} is empty.
 217      *
 218      * @return an {@code Optional} containing this client's {@code CookieManager}
 219      */
 220     public abstract Optional<CookieManager> cookieManager();
 221 
 222     /**
 223      * Returns the follow-redirects setting for this client. The default value
 224      * for this setting is {@link HttpClient.Redirect#NEVER}
 225      *
 226      * @return this client's follow redirects setting
 227      */
 228     public abstract Redirect followRedirects();
 229 
 230     /**
 231      * Returns an {@code Optional} containing the {@code ProxySelector} for this client.
 232      * If no proxy is set then the {@code Optional} is empty.
 233      *
 234      * @return an {@code Optional} containing this client's proxy selector
 235      */
 236     public abstract Optional<ProxySelector> proxy();
 237 
 238     /**
 239      * Returns the {@code SSLContext}, if one was set on this client. If a security
 240      * manager is set, then the caller must have the
 241      * {@link java.net.NetPermission NetPermission}("getSSLContext") permission.
 242      * If no {@code SSLContext} was set, then the default context is returned.
 243      *
 244      * @return this client's SSLContext
 245      * @throws SecurityException if the caller does not have permission to get
 246      *         the SSLContext
 247      */
 248     public abstract SSLContext sslContext();
 249 
 250     /**
 251      * Returns an {@code Optional} containing the {@link SSLParameters} set on
 252      * this client. If no {@code SSLParameters} were set in the client's builder,
 253      * then the {@code Optional} is empty.
 254      *
 255      * @return an {@code Optional} containing this client's {@code SSLParameters}
 256      */
 257     public abstract Optional<SSLParameters> sslParameters();
 258 
 259     /**
 260      * Returns an {@code Optional} containing the {@link Authenticator} set on
 261      * this client. If no {@code Authenticator} was set in the client's builder,
 262      * then the {@code Optional} is empty.
 263      *
 264      * @return an {@code Optional} containing this client's {@code Authenticator}
 265      */
 266     public abstract Optional<Authenticator> authenticator();
 267 
 268     /**
 269      * Returns the HTTP protocol version requested for this client. The default
 270      * value is {@link HttpClient.Version#HTTP_2}
 271      *
 272      * @return the HTTP protocol version requested
 273      */
 274     public abstract HttpClient.Version version();
 275 
 276     /**
 277      * Returns the {@code Executor} set on this client. If an {@code
 278      * Executor} was not set on the client's builder, then a default
 279      * object is returned. The default {@code Executor} is created independently
 280      * for each client.
 281      *
 282      * @return this client's Executor
 283      */
 284     public abstract Executor executor();
 285 
 286     /**
 287      * The HTTP protocol version.
 288      * {@Incubating}
 289      *
 290      * @since 9
 291      */
 292     public enum Version {
 293 
 294         /**
 295          * HTTP version 1.1
 296          */
 297         HTTP_1_1,
 298 
 299         /**
 300          * HTTP version 2
 301          */
 302         HTTP_2
 303     }
 304 
 305     /**
 306      * Defines automatic redirection policy.
 307      * {@Incubating}
 308      *
 309      * <p> This is checked whenever a {@code 3XX} response code is received. If
 310      * redirection does not happen automatically then the response is returned
 311      * to the user, where it can be handled manually.
 312      *
 313      * <p> {@code Redirect} policy is set via the {@link
 314      * HttpClient.Builder#followRedirects(HttpClient.Redirect)} method.
 315      *
 316      * @since 9
 317      */
 318     public enum Redirect {
 319 
 320         /**
 321          * Never redirect.
 322          */
 323         NEVER,
 324 
 325         /**
 326          * Always redirect.
 327          */
 328         ALWAYS,
 329 
 330         /**
 331          * Redirect to same protocol only. Redirection may occur from HTTP URLs
 332          * to other HTTP URLs, and from HTTPS URLs to other HTTPS URLs.
 333          */
 334         SAME_PROTOCOL,
 335 
 336         /**
 337          * Redirect always except from HTTPS URLs to HTTP URLs.
 338          */
 339         SECURE
 340     }
 341 
 342     /**
 343      * Sends the given request using this client, blocking if necessary to get
 344      * the response. The returned {@link HttpResponse}{@code <T>} contains the
 345      * response status, headers, and body ( as handled by given response body
 346      * handler ).
 347      *
 348      * @param <T> the response body type
 349      * @param req the request
 350      * @param responseBodyHandler the response body handler
 351      * @return the response body
 352      * @throws java.io.IOException if an I/O error occurs when sending or receiving
 353      * @throws java.lang.InterruptedException if the operation is interrupted
 354      */
 355     public abstract <T> HttpResponse<T>
 356     send(HttpRequest req, HttpResponse.BodyHandler<T> responseBodyHandler)
 357         throws IOException, InterruptedException;
 358 
 359     /**
 360      * Sends the given request asynchronously using this client and the given
 361      * response handler.
 362      *
 363      * @param <T> the response body type
 364      * @param req the request
 365      * @param responseBodyHandler the response body handler
 366      * @return a {@code CompletableFuture<HttpResponse<T>>}
 367      */
 368     public abstract <T> CompletableFuture<HttpResponse<T>>
 369     sendAsync(HttpRequest req, HttpResponse.BodyHandler<T> responseBodyHandler);
 370 
 371     /**
 372      * Sends the given request asynchronously using this client and the given
 373      * multi response handler.
 374      *
 375      * @param <U> a type representing the aggregated results
 376      * @param <T> a type representing all of the response bodies
 377      * @param req the request
 378      * @param multiProcessor the MultiProcessor for the request
 379      * @return a {@code CompletableFuture<U>}
 380      */
 381     public abstract <U, T> CompletableFuture<U>
 382     sendAsync(HttpRequest req, HttpResponse.MultiProcessor<U, T> multiProcessor);
 383 
 384     /**
 385      * Creates a builder of {@link WebSocket} instances connected to the given
 386      * URI and receiving events and messages with the given {@code Listener}.
 387      *
 388      * <p> <b>Example</b>
 389      * <pre>{@code
 390      *     HttpClient client = HttpClient.newHttpClient();
 391      *     WebSocket.Builder builder = client.newWebSocketBuilder(
 392      *             URI.create("ws://websocket.example.com"),
 393      *             listener);
 394      * }</pre>
 395      *
 396      * <p> Finer control over the WebSocket Opening Handshake can be achieved
 397      * by using a custom {@code HttpClient}.
 398      *
 399      * <p> <b>Example</b>
 400      * <pre>{@code
 401      *     InetSocketAddress addr = new InetSocketAddress("proxy.example.com", 80);
 402      *     HttpClient client = HttpClient.newBuilder()
 403      *             .proxy(ProxySelector.of(addr))
 404      *             .build();
 405      *     WebSocket.Builder builder = client.newWebSocketBuilder(
 406      *             URI.create("ws://websocket.example.com"),
 407      *             listener);
 408      * }</pre>
 409      *
 410      * @implSpec The default implementation of this method throws {@code
 411      * UnsupportedOperationException}. However, clients obtained through
 412      * {@link HttpClient#newHttpClient()} or {@link HttpClient#newBuilder()}
 413      * provide WebSocket capability.
 414      *
 415      * @param uri
 416      *         the WebSocket URI
 417      * @param listener
 418      *         the listener
 419      *
 420      * @return a builder of {@code WebSocket} instances
 421      * @throws UnsupportedOperationException
 422      *         if this {@code HttpClient} does not provide WebSocket support
 423      */
 424     public WebSocket.Builder newWebSocketBuilder(URI uri,
 425                                                  WebSocket.Listener listener)
 426     {
 427         throw new UnsupportedOperationException();
 428     }
 429 }