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
26package jdk.incubator.http;
27
28import java.io.IOException;
29import java.net.Authenticator;
30import java.net.CookieManager;
31import java.net.InetSocketAddress;
32import java.net.ProxySelector;
33import java.net.URI;
34import java.util.Optional;
35import java.util.concurrent.CompletableFuture;
36import java.util.concurrent.Executor;
37import javax.net.ssl.SSLContext;
38import 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 */
53public 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}
430