View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.client5.http.impl.async;
29  
30  import org.apache.hc.client5.http.DnsResolver;
31  import org.apache.hc.client5.http.SchemePortResolver;
32  import org.apache.hc.client5.http.SystemDefaultDnsResolver;
33  import org.apache.hc.client5.http.config.TlsConfig;
34  import org.apache.hc.client5.http.impl.DefaultClientConnectionReuseStrategy;
35  import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
36  import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
37  import org.apache.hc.client5.http.nio.AsyncClientConnectionManager;
38  import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
39  import org.apache.hc.core5.concurrent.DefaultThreadFactory;
40  import org.apache.hc.core5.function.Supplier;
41  import org.apache.hc.core5.http.config.CharCodingConfig;
42  import org.apache.hc.core5.http.config.Http1Config;
43  import org.apache.hc.core5.http.impl.routing.RequestRouter;
44  import org.apache.hc.core5.http.nio.AsyncPushConsumer;
45  import org.apache.hc.core5.http.nio.HandlerFactory;
46  import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
47  import org.apache.hc.core5.http.protocol.DefaultHttpProcessor;
48  import org.apache.hc.core5.http.protocol.HttpProcessor;
49  import org.apache.hc.core5.http.protocol.RequestUserAgent;
50  import org.apache.hc.core5.http2.HttpVersionPolicy;
51  import org.apache.hc.core5.http2.config.H2Config;
52  import org.apache.hc.core5.http2.protocol.H2RequestConnControl;
53  import org.apache.hc.core5.http2.protocol.H2RequestContent;
54  import org.apache.hc.core5.http2.protocol.H2RequestTargetHost;
55  import org.apache.hc.core5.reactor.IOEventHandlerFactory;
56  import org.apache.hc.core5.reactor.IOReactorConfig;
57  import org.apache.hc.core5.util.VersionInfo;
58  
59  /**
60   * Factory methods for {@link CloseableHttpAsyncClient} instances.
61   *
62   * @since 5.0
63   */
64  public final class HttpAsyncClients {
65  
66      private HttpAsyncClients() {
67          super();
68      }
69  
70      /**
71       * Creates builder object for construction of custom
72       * {@link CloseableHttpAsyncClient} instances.
73       */
74      public static HttpAsyncClientBuilder custom() {
75          return HttpAsyncClientBuilder.create();
76      }
77  
78      /**
79       * Creates {@link CloseableHttpAsyncClient} instance with default configuration.
80       */
81      public static CloseableHttpAsyncClient createDefault() {
82          return HttpAsyncClientBuilder.create().build();
83      }
84  
85      /**
86       * Creates {@link CloseableHttpAsyncClient} instance with default
87       * configuration and system properties.
88       */
89      public static CloseableHttpAsyncClient createSystem() {
90          return HttpAsyncClientBuilder.create().useSystemProperties().build();
91      }
92  
93      /**
94       * Creates builder object for construction of custom HTTP/2
95       * {@link CloseableHttpAsyncClient} instances optimized for HTTP/2 protocol
96       * and message multiplexing
97       */
98      public static H2AsyncClientBuilder customHttp2() {
99          return H2AsyncClientBuilder.create();
100     }
101 
102     /**
103      * Creates HTTP/2 {@link CloseableHttpAsyncClient} instance with default configuration
104      * optimized for HTTP/2 protocol and message multiplexing.
105      */
106     public static CloseableHttpAsyncClient createHttp2Default() {
107         return H2AsyncClientBuilder.create().build();
108     }
109 
110     /**
111      * Creates HTTP/2 {@link CloseableHttpAsyncClient} instance with default configuration and
112      * system properties optimized for HTTP/2 protocol and message multiplexing.
113      */
114     public static CloseableHttpAsyncClient createHttp2System() {
115         return H2AsyncClientBuilder.create().useSystemProperties().build();
116     }
117 
118     private static HttpProcessor createMinimalProtocolProcessor() {
119         return new DefaultHttpProcessor(
120                 new H2RequestTargetHost(),
121                 new H2RequestContent(),
122                 new H2RequestConnControl(),
123                 new RequestUserAgent(VersionInfo.getSoftwareInfo(
124                         "Apache-HttpAsyncClient", "org.apache.hc.client5", HttpAsyncClients.class)));
125     }
126 
127     private static MinimalHttpAsyncClient createMinimalHttpAsyncClientImpl(
128             final IOEventHandlerFactory eventHandlerFactory,
129             final AsyncPushConsumerRegistry pushConsumerRegistry,
130             final IOReactorConfig ioReactorConfig,
131             final AsyncClientConnectionManager connmgr,
132             final SchemePortResolver schemePortResolver,
133             final TlsConfig tlsConfig) {
134         return new MinimalHttpAsyncClient(
135                 eventHandlerFactory,
136                 pushConsumerRegistry,
137                 ioReactorConfig,
138                 new DefaultThreadFactory("httpclient-main", true),
139                 new DefaultThreadFactory("httpclient-dispatch", true),
140                 connmgr,
141                 schemePortResolver,
142                 tlsConfig);
143     }
144 
145     /**
146      * Creates {@link MinimalHttpAsyncClient} instance optimized for
147      * HTTP/1.1 and HTTP/2 message transport without advanced HTTP protocol
148      * functionality.
149      *
150      * @deprecated Use {@link #createMinimal(H2Config, Http1Config, IOReactorConfig, AsyncClientConnectionManager)}
151      */
152     @Deprecated
153     public static MinimalHttpAsyncClient createMinimal(
154             final HttpVersionPolicy versionPolicy,
155             final H2Config h2Config,
156             final Http1Config h1Config,
157             final IOReactorConfig ioReactorConfig,
158             final AsyncClientConnectionManager connmgr) {
159         final AsyncPushConsumerRegistry pushConsumerRegistry = new AsyncPushConsumerRegistry();
160         return createMinimalHttpAsyncClientImpl(
161                 new HttpAsyncClientProtocolNegotiationStarter(
162                         createMinimalProtocolProcessor(),
163                         (request, context) -> pushConsumerRegistry.get(request),
164                         h2Config,
165                         h1Config,
166                         CharCodingConfig.DEFAULT,
167                         DefaultClientConnectionReuseStrategy.INSTANCE),
168                 pushConsumerRegistry,
169                 ioReactorConfig,
170                 connmgr,
171                 DefaultSchemePortResolver.INSTANCE,
172                 versionPolicy != null ? TlsConfig.custom().setVersionPolicy(versionPolicy).build() : null);
173     }
174 
175     /**
176      * Creates {@link MinimalHttpAsyncClient} instance optimized for
177      * HTTP/1.1 and HTTP/2 message transport without advanced HTTP protocol
178      * functionality.
179      *
180      * @since 5.2
181      */
182     public static MinimalHttpAsyncClient createMinimal(
183             final H2Config h2Config,
184             final Http1Config h1Config,
185             final IOReactorConfig ioReactorConfig,
186             final AsyncClientConnectionManager connmgr) {
187         final AsyncPushConsumerRegistry pushConsumerRegistry = new AsyncPushConsumerRegistry();
188         return createMinimalHttpAsyncClientImpl(
189                 new HttpAsyncClientProtocolNegotiationStarter(
190                         createMinimalProtocolProcessor(),
191                         (request, context) -> pushConsumerRegistry.get(request),
192                         h2Config,
193                         h1Config,
194                         CharCodingConfig.DEFAULT,
195                         DefaultClientConnectionReuseStrategy.INSTANCE),
196                 pushConsumerRegistry,
197                 ioReactorConfig,
198                 connmgr,
199                 DefaultSchemePortResolver.INSTANCE,
200                 null);
201     }
202 
203     /**
204      * Creates {@link MinimalHttpAsyncClient} instance optimized for
205      * HTTP/1.1 and HTTP/2 message transport without advanced HTTP protocol
206      * functionality.
207      *
208      * @deprecated Use {@link #createMinimal(H2Config, Http1Config, IOReactorConfig)}
209      */
210     @Deprecated
211     public static MinimalHttpAsyncClient createMinimal(
212             final HttpVersionPolicy versionPolicy,
213             final H2Config h2Config,
214             final Http1Config h1Config,
215             final IOReactorConfig ioReactorConfig) {
216         return createMinimal(versionPolicy, h2Config, h1Config, ioReactorConfig,
217                 PoolingAsyncClientConnectionManagerBuilder.create().build());
218     }
219 
220     /**
221      * Creates {@link MinimalHttpAsyncClient} instance optimized for
222      * HTTP/1.1 and HTTP/2 message transport without advanced HTTP protocol
223      * functionality.
224      */
225     public static MinimalHttpAsyncClient createMinimal(
226             final H2Config h2Config,
227             final Http1Config h1Config,
228             final IOReactorConfig ioReactorConfig) {
229         return createMinimal(h2Config, h1Config, ioReactorConfig,
230                 PoolingAsyncClientConnectionManagerBuilder.create().build());
231     }
232 
233     /**
234      * Creates {@link MinimalHttpAsyncClient} instance optimized for
235      * HTTP/1.1 and HTTP/2 message transport without advanced HTTP protocol
236      * functionality.
237      */
238     public static MinimalHttpAsyncClient createMinimal(final H2Config h2Config, final Http1Config h1Config) {
239         return createMinimal(HttpVersionPolicy.NEGOTIATE, h2Config, h1Config, IOReactorConfig.DEFAULT);
240     }
241 
242     /**
243      * Creates {@link MinimalHttpAsyncClient} instance optimized for
244      * HTTP/1.1 and HTTP/2 message transport without advanced HTTP protocol
245      * functionality.
246      */
247     public static MinimalHttpAsyncClient createMinimal() {
248         return createMinimal(H2Config.DEFAULT, Http1Config.DEFAULT);
249     }
250 
251     /**
252      * Creates {@link MinimalHttpAsyncClient} instance optimized for
253      * HTTP/1.1 and HTTP/2 message transport without advanced HTTP protocol
254      * functionality.
255      */
256     public static MinimalHttpAsyncClient createMinimal(final AsyncClientConnectionManager connManager) {
257         return createMinimal(
258                 HttpVersionPolicy.NEGOTIATE,
259                 H2Config.DEFAULT,
260                 Http1Config.DEFAULT,
261                 IOReactorConfig.DEFAULT,
262                 connManager);
263     }
264 
265     private static MinimalH2AsyncClient createMinimalHttp2AsyncClientImpl(
266             final IOEventHandlerFactory eventHandlerFactory,
267             final AsyncPushConsumerRegistry pushConsumerRegistry,
268             final IOReactorConfig ioReactorConfig,
269             final DnsResolver dnsResolver,
270             final TlsStrategy tlsStrategy) {
271         return new MinimalH2AsyncClient(
272                 eventHandlerFactory,
273                 pushConsumerRegistry,
274                 ioReactorConfig,
275                 new DefaultThreadFactory("httpclient-main", true),
276                 new DefaultThreadFactory("httpclient-dispatch", true),
277                 dnsResolver,
278                 tlsStrategy);
279     }
280 
281     /**
282      * Creates {@link MinimalH2AsyncClient} instance optimized for HTTP/2 multiplexing message
283      * transport without advanced HTTP protocol functionality.
284      */
285     public static MinimalH2AsyncClient createHttp2Minimal(
286             final H2Config h2Config,
287             final IOReactorConfig ioReactorConfig,
288             final DnsResolver dnsResolver,
289             final TlsStrategy tlsStrategy) {
290         final AsyncPushConsumerRegistry pushConsumerRegistry = new AsyncPushConsumerRegistry();
291         return createMinimalHttp2AsyncClientImpl(
292                 new H2AsyncClientProtocolStarter(
293                         createMinimalProtocolProcessor(),
294                         (request, context) -> pushConsumerRegistry.get(request),
295                         h2Config,
296                         CharCodingConfig.DEFAULT),
297                 pushConsumerRegistry,
298                 ioReactorConfig,
299                 dnsResolver,
300                 tlsStrategy);
301     }
302 
303     /**
304      * Creates {@link MinimalH2AsyncClient} instance optimized for HTTP/2 multiplexing message
305      * transport without advanced HTTP protocol functionality.
306      */
307     public static MinimalH2AsyncClient createHttp2Minimal(
308             final H2Config h2Config,
309             final IOReactorConfig ioReactorConfig,
310             final TlsStrategy tlsStrategy) {
311         return createHttp2Minimal(h2Config, ioReactorConfig, SystemDefaultDnsResolver.INSTANCE, tlsStrategy);
312     }
313 
314     /**
315      * Creates {@link MinimalH2AsyncClient} instance optimized for HTTP/2 multiplexing message
316      * transport without advanced HTTP protocol functionality.
317      */
318     public static MinimalH2AsyncClient createHttp2Minimal(
319             final H2Config h2Config,
320             final IOReactorConfig ioReactorConfig) {
321         return createHttp2Minimal(h2Config, ioReactorConfig, DefaultClientTlsStrategy.createDefault());
322     }
323 
324     /**
325      * Creates {@link MinimalH2AsyncClient} instance optimized for HTTP/2 multiplexing message
326      * transport without advanced HTTP protocol functionality.
327      */
328     public static MinimalH2AsyncClient createHttp2Minimal(final H2Config h2Config) {
329         return createHttp2Minimal(h2Config, IOReactorConfig.DEFAULT);
330     }
331 
332     /**
333      * Creates {@link MinimalH2AsyncClient} instance optimized for HTTP/2 multiplexing message
334      * transport without advanced HTTP protocol functionality.
335      */
336     public static MinimalH2AsyncClient createHttp2Minimal() {
337         return createHttp2Minimal(H2Config.DEFAULT);
338     }
339 
340     /**
341      * Creates {@link HandlerFactory} backed by a push {@link RequestRouter}.
342      *
343      * @since 5.4
344      */
345     public static HandlerFactory<AsyncPushConsumer> pushRouter(final RequestRouter<Supplier<AsyncPushConsumer>> requestRouter) {
346         return (request, context) -> {
347             final Supplier<AsyncPushConsumer> supplier = requestRouter.resolve(request, context);
348             return supplier != null ? supplier.get() : null;
349         };
350     }
351 
352 }