1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.client5.http.impl.async;
29
30 import java.io.Closeable;
31 import java.io.IOException;
32 import java.net.ProxySelector;
33 import java.security.AccessController;
34 import java.security.PrivilegedAction;
35 import java.util.ArrayList;
36 import java.util.Collection;
37 import java.util.LinkedList;
38 import java.util.List;
39 import java.util.concurrent.ThreadFactory;
40
41 import org.apache.hc.client5.http.AuthenticationStrategy;
42 import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
43 import org.apache.hc.client5.http.HttpRequestRetryStrategy;
44 import org.apache.hc.client5.http.SchemePortResolver;
45 import org.apache.hc.client5.http.UserTokenHandler;
46 import org.apache.hc.client5.http.async.AsyncExecChainHandler;
47 import org.apache.hc.client5.http.auth.AuthSchemeFactory;
48 import org.apache.hc.client5.http.auth.StandardAuthScheme;
49 import org.apache.hc.client5.http.auth.CredentialsProvider;
50 import org.apache.hc.client5.http.config.RequestConfig;
51 import org.apache.hc.client5.http.cookie.BasicCookieStore;
52 import org.apache.hc.client5.http.cookie.CookieSpecFactory;
53 import org.apache.hc.client5.http.cookie.CookieStore;
54 import org.apache.hc.client5.http.impl.ChainElement;
55 import org.apache.hc.client5.http.impl.CookieSpecSupport;
56 import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy;
57 import org.apache.hc.client5.http.impl.DefaultConnectionKeepAliveStrategy;
58 import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy;
59 import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
60 import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
61 import org.apache.hc.client5.http.impl.DefaultUserTokenHandler;
62 import org.apache.hc.client5.http.impl.IdleConnectionEvictor;
63 import org.apache.hc.client5.http.impl.NoopUserTokenHandler;
64 import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
65 import org.apache.hc.client5.http.impl.auth.BasicSchemeFactory;
66 import org.apache.hc.client5.http.impl.auth.DigestSchemeFactory;
67 import org.apache.hc.client5.http.impl.auth.KerberosSchemeFactory;
68 import org.apache.hc.client5.http.impl.auth.NTLMSchemeFactory;
69 import org.apache.hc.client5.http.impl.auth.SPNegoSchemeFactory;
70 import org.apache.hc.client5.http.impl.auth.SystemDefaultCredentialsProvider;
71 import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
72 import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner;
73 import org.apache.hc.client5.http.impl.routing.DefaultRoutePlanner;
74 import org.apache.hc.client5.http.impl.routing.SystemDefaultRoutePlanner;
75 import org.apache.hc.client5.http.nio.AsyncClientConnectionManager;
76 import org.apache.hc.client5.http.protocol.RedirectStrategy;
77 import org.apache.hc.client5.http.protocol.RequestAddCookies;
78 import org.apache.hc.client5.http.protocol.RequestAuthCache;
79 import org.apache.hc.client5.http.protocol.RequestDefaultHeaders;
80 import org.apache.hc.client5.http.protocol.RequestExpectContinue;
81 import org.apache.hc.client5.http.protocol.ResponseProcessCookies;
82 import org.apache.hc.client5.http.routing.HttpRoutePlanner;
83 import org.apache.hc.core5.annotation.Internal;
84 import org.apache.hc.core5.concurrent.DefaultThreadFactory;
85 import org.apache.hc.core5.function.Callback;
86 import org.apache.hc.core5.http.ConnectionReuseStrategy;
87 import org.apache.hc.core5.http.Header;
88 import org.apache.hc.core5.http.HttpException;
89 import org.apache.hc.core5.http.HttpHost;
90 import org.apache.hc.core5.http.HttpRequest;
91 import org.apache.hc.core5.http.HttpRequestInterceptor;
92 import org.apache.hc.core5.http.HttpResponse;
93 import org.apache.hc.core5.http.HttpResponseInterceptor;
94 import org.apache.hc.core5.http.config.CharCodingConfig;
95 import org.apache.hc.core5.http.config.Http1Config;
96 import org.apache.hc.core5.http.config.Lookup;
97 import org.apache.hc.core5.http.config.NamedElementChain;
98 import org.apache.hc.core5.http.config.RegistryBuilder;
99 import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
100 import org.apache.hc.core5.http.nio.AsyncPushConsumer;
101 import org.apache.hc.core5.http.nio.HandlerFactory;
102 import org.apache.hc.core5.http.nio.command.ShutdownCommand;
103 import org.apache.hc.core5.http.protocol.DefaultHttpProcessor;
104 import org.apache.hc.core5.http.protocol.HttpContext;
105 import org.apache.hc.core5.http.protocol.HttpProcessor;
106 import org.apache.hc.core5.http.protocol.HttpProcessorBuilder;
107 import org.apache.hc.core5.http.protocol.RequestTargetHost;
108 import org.apache.hc.core5.http.protocol.RequestUserAgent;
109 import org.apache.hc.core5.http2.HttpVersionPolicy;
110 import org.apache.hc.core5.http2.config.H2Config;
111 import org.apache.hc.core5.http2.protocol.H2RequestConnControl;
112 import org.apache.hc.core5.http2.protocol.H2RequestContent;
113 import org.apache.hc.core5.http2.protocol.H2RequestTargetHost;
114 import org.apache.hc.core5.io.CloseMode;
115 import org.apache.hc.core5.pool.ConnPoolControl;
116 import org.apache.hc.core5.reactor.Command;
117 import org.apache.hc.core5.reactor.DefaultConnectingIOReactor;
118 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
119 import org.apache.hc.core5.reactor.IOReactorConfig;
120 import org.apache.hc.core5.reactor.IOSession;
121 import org.apache.hc.core5.util.Args;
122 import org.apache.hc.core5.util.TimeValue;
123 import org.apache.hc.core5.util.VersionInfo;
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 public class HttpAsyncClientBuilder {
159
160 private static class RequestInterceptorEntry {
161
162 enum Postion { FIRST, LAST }
163
164 final RequestInterceptorEntry.Postion postion;
165 final HttpRequestInterceptor interceptor;
166
167 private RequestInterceptorEntry(final RequestInterceptorEntry.Postion postion, final HttpRequestInterceptor interceptor) {
168 this.postion = postion;
169 this.interceptor = interceptor;
170 }
171 }
172
173 private static class ResponseInterceptorEntry {
174
175 enum Postion { FIRST, LAST }
176
177 final ResponseInterceptorEntry.Postion postion;
178 final HttpResponseInterceptor interceptor;
179
180 private ResponseInterceptorEntry(final ResponseInterceptorEntry.Postion postion, final HttpResponseInterceptor interceptor) {
181 this.postion = postion;
182 this.interceptor = interceptor;
183 }
184 }
185
186 private static class ExecInterceptorEntry {
187
188 enum Postion { BEFORE, AFTER, REPLACE, FIRST, LAST }
189
190 final ExecInterceptorEntry.Postion postion;
191 final String name;
192 final AsyncExecChainHandler interceptor;
193 final String existing;
194
195 private ExecInterceptorEntry(
196 final ExecInterceptorEntry.Postion postion,
197 final String name,
198 final AsyncExecChainHandler interceptor,
199 final String existing) {
200 this.postion = postion;
201 this.name = name;
202 this.interceptor = interceptor;
203 this.existing = existing;
204 }
205
206 }
207
208 private HttpVersionPolicy versionPolicy;
209 private AsyncClientConnectionManager connManager;
210 private boolean connManagerShared;
211 private IOReactorConfig ioReactorConfig;
212 private Http1Config h1Config;
213 private H2Config h2Config;
214 private CharCodingConfig charCodingConfig;
215 private SchemePortResolver schemePortResolver;
216 private ConnectionKeepAliveStrategy keepAliveStrategy;
217 private UserTokenHandler userTokenHandler;
218 private AuthenticationStrategy targetAuthStrategy;
219 private AuthenticationStrategy proxyAuthStrategy;
220
221 private LinkedList<RequestInterceptorEntry> requestInterceptors;
222 private LinkedList<ResponseInterceptorEntry> responseInterceptors;
223 private LinkedList<ExecInterceptorEntry> execInterceptors;
224
225 private HttpRoutePlanner routePlanner;
226 private RedirectStrategy redirectStrategy;
227 private HttpRequestRetryStrategy retryStrategy;
228
229 private ConnectionReuseStrategy reuseStrategy;
230
231 private Lookup<AuthSchemeFactory> authSchemeRegistry;
232 private Lookup<CookieSpecFactory> cookieSpecRegistry;
233 private CookieStore cookieStore;
234 private CredentialsProvider credentialsProvider;
235
236 private String userAgent;
237 private HttpHost proxy;
238 private Collection<? extends Header> defaultHeaders;
239 private RequestConfig defaultRequestConfig;
240 private boolean evictExpiredConnections;
241 private boolean evictIdleConnections;
242 private TimeValue maxIdleTime;
243
244 private boolean systemProperties;
245 private boolean automaticRetriesDisabled;
246 private boolean redirectHandlingDisabled;
247 private boolean cookieManagementDisabled;
248 private boolean authCachingDisabled;
249 private boolean connectionStateDisabled;
250
251 private ThreadFactory threadFactory;
252
253 private List<Closeable> closeables;
254
255 public static HttpAsyncClientBuilder create() {
256 return new HttpAsyncClientBuilder();
257 }
258
259 protected HttpAsyncClientBuilder() {
260 super();
261 }
262
263
264
265
266 public final HttpAsyncClientBuilder setVersionPolicy(final HttpVersionPolicy versionPolicy) {
267 this.versionPolicy = versionPolicy;
268 return this;
269 }
270
271
272
273
274 public final HttpAsyncClientBuilder setHttp1Config(final Http1Config h1Config) {
275 this.h1Config = h1Config;
276 return this;
277 }
278
279
280
281
282 public final HttpAsyncClientBuilder setH2Config(final H2Config h2Config) {
283 this.h2Config = h2Config;
284 return this;
285 }
286
287
288
289
290 public final HttpAsyncClientBuilder setConnectionManager(final AsyncClientConnectionManager connManager) {
291 this.connManager = connManager;
292 return this;
293 }
294
295
296
297
298
299
300
301
302
303
304
305
306 public final HttpAsyncClientBuilder setConnectionManagerShared(final boolean shared) {
307 this.connManagerShared = shared;
308 return this;
309 }
310
311
312
313
314 public final HttpAsyncClientBuilder setIOReactorConfig(final IOReactorConfig ioReactorConfig) {
315 this.ioReactorConfig = ioReactorConfig;
316 return this;
317 }
318
319
320
321
322 public final HttpAsyncClientBuilder setCharCodingConfig(final CharCodingConfig charCodingConfig) {
323 this.charCodingConfig = charCodingConfig;
324 return this;
325 }
326
327
328
329
330
331
332 public final HttpAsyncClientBuilder setConnectionReuseStrategy(final ConnectionReuseStrategy reuseStrategy) {
333 this.reuseStrategy = reuseStrategy;
334 return this;
335 }
336
337
338
339
340 public final HttpAsyncClientBuilder setKeepAliveStrategy(final ConnectionKeepAliveStrategy keepAliveStrategy) {
341 this.keepAliveStrategy = keepAliveStrategy;
342 return this;
343 }
344
345
346
347
348
349
350
351
352 public final HttpAsyncClientBuilder setUserTokenHandler(final UserTokenHandler userTokenHandler) {
353 this.userTokenHandler = userTokenHandler;
354 return this;
355 }
356
357
358
359
360
361 public final HttpAsyncClientBuilder setTargetAuthenticationStrategy(
362 final AuthenticationStrategy targetAuthStrategy) {
363 this.targetAuthStrategy = targetAuthStrategy;
364 return this;
365 }
366
367
368
369
370
371 public final HttpAsyncClientBuilder setProxyAuthenticationStrategy(
372 final AuthenticationStrategy proxyAuthStrategy) {
373 this.proxyAuthStrategy = proxyAuthStrategy;
374 return this;
375 }
376
377
378
379
380 public final HttpAsyncClientBuilder addResponseInterceptorFirst(final HttpResponseInterceptor interceptor) {
381 Args.notNull(interceptor, "Interceptor");
382 if (responseInterceptors == null) {
383 responseInterceptors = new LinkedList<>();
384 }
385 responseInterceptors.add(new ResponseInterceptorEntry(ResponseInterceptorEntry.Postion.FIRST, interceptor));
386 return this;
387 }
388
389
390
391
392 public final HttpAsyncClientBuilder addResponseInterceptorLast(final HttpResponseInterceptor interceptor) {
393 Args.notNull(interceptor, "Interceptor");
394 if (responseInterceptors == null) {
395 responseInterceptors = new LinkedList<>();
396 }
397 responseInterceptors.add(new ResponseInterceptorEntry(ResponseInterceptorEntry.Postion.LAST, interceptor));
398 return this;
399 }
400
401
402
403
404 public final HttpAsyncClientBuilder addExecInterceptorBefore(final String existing, final String name, final AsyncExecChainHandler interceptor) {
405 Args.notBlank(existing, "Existing");
406 Args.notBlank(name, "Name");
407 Args.notNull(interceptor, "Interceptor");
408 if (execInterceptors == null) {
409 execInterceptors = new LinkedList<>();
410 }
411 execInterceptors.add(new ExecInterceptorEntry(ExecInterceptorEntry.Postion.BEFORE, name, interceptor, existing));
412 return this;
413 }
414
415
416
417
418 public final HttpAsyncClientBuilder addExecInterceptorAfter(final String existing, final String name, final AsyncExecChainHandler interceptor) {
419 Args.notBlank(existing, "Existing");
420 Args.notBlank(name, "Name");
421 Args.notNull(interceptor, "Interceptor");
422 if (execInterceptors == null) {
423 execInterceptors = new LinkedList<>();
424 }
425 execInterceptors.add(new ExecInterceptorEntry(ExecInterceptorEntry.Postion.AFTER, name, interceptor, existing));
426 return this;
427 }
428
429
430
431
432 public final HttpAsyncClientBuilder replaceExecInterceptor(final String existing, final AsyncExecChainHandler interceptor) {
433 Args.notBlank(existing, "Existing");
434 Args.notNull(interceptor, "Interceptor");
435 if (execInterceptors == null) {
436 execInterceptors = new LinkedList<>();
437 }
438 execInterceptors.add(new ExecInterceptorEntry(ExecInterceptorEntry.Postion.REPLACE, existing, interceptor, existing));
439 return this;
440 }
441
442
443
444
445 public final HttpAsyncClientBuilder addExecInterceptorFirst(final String name, final AsyncExecChainHandler interceptor) {
446 Args.notNull(name, "Name");
447 Args.notNull(interceptor, "Interceptor");
448 execInterceptors.add(new ExecInterceptorEntry(ExecInterceptorEntry.Postion.FIRST, name, interceptor, null));
449 return this;
450 }
451
452
453
454
455 public final HttpAsyncClientBuilder addExecInterceptorLast(final String name, final AsyncExecChainHandler interceptor) {
456 Args.notNull(name, "Name");
457 Args.notNull(interceptor, "Interceptor");
458 execInterceptors.add(new ExecInterceptorEntry(ExecInterceptorEntry.Postion.LAST, name, interceptor, null));
459 return this;
460 }
461
462
463
464
465 public final HttpAsyncClientBuilder addRequestInterceptorFirst(final HttpRequestInterceptor interceptor) {
466 Args.notNull(interceptor, "Interceptor");
467 if (requestInterceptors == null) {
468 requestInterceptors = new LinkedList<>();
469 }
470 requestInterceptors.add(new RequestInterceptorEntry(RequestInterceptorEntry.Postion.FIRST, interceptor));
471 return this;
472 }
473
474
475
476
477 public final HttpAsyncClientBuilder addRequestInterceptorLast(final HttpRequestInterceptor interceptor) {
478 Args.notNull(interceptor, "Interceptor");
479 if (requestInterceptors == null) {
480 requestInterceptors = new LinkedList<>();
481 }
482 requestInterceptors.add(new RequestInterceptorEntry(RequestInterceptorEntry.Postion.LAST, interceptor));
483 return this;
484 }
485
486
487
488
489
490
491
492 public final HttpAsyncClientBuilder setRetryStrategy(final HttpRequestRetryStrategy retryStrategy) {
493 this.retryStrategy = retryStrategy;
494 return this;
495 }
496
497
498
499
500
501
502
503
504 public HttpAsyncClientBuilder setRedirectStrategy(final RedirectStrategy redirectStrategy) {
505 this.redirectStrategy = redirectStrategy;
506 return this;
507 }
508
509
510
511
512 public final HttpAsyncClientBuilder setSchemePortResolver(final SchemePortResolver schemePortResolver) {
513 this.schemePortResolver = schemePortResolver;
514 return this;
515 }
516
517
518
519
520 public final HttpAsyncClientBuilder setThreadFactory(final ThreadFactory threadFactory) {
521 this.threadFactory = threadFactory;
522 return this;
523 }
524
525
526
527
528 public final HttpAsyncClientBuilder setUserAgent(final String userAgent) {
529 this.userAgent = userAgent;
530 return this;
531 }
532
533
534
535
536 public final HttpAsyncClientBuilder setDefaultHeaders(final Collection<? extends Header> defaultHeaders) {
537 this.defaultHeaders = defaultHeaders;
538 return this;
539 }
540
541
542
543
544
545
546
547 public final HttpAsyncClientBuilder setProxy(final HttpHost proxy) {
548 this.proxy = proxy;
549 return this;
550 }
551
552
553
554
555 public final HttpAsyncClientBuilder setRoutePlanner(final HttpRoutePlanner routePlanner) {
556 this.routePlanner = routePlanner;
557 return this;
558 }
559
560
561
562
563
564
565 public final HttpAsyncClientBuilder setDefaultCredentialsProvider(final CredentialsProvider credentialsProvider) {
566 this.credentialsProvider = credentialsProvider;
567 return this;
568 }
569
570
571
572
573
574
575 public final HttpAsyncClientBuilder setDefaultAuthSchemeRegistry(final Lookup<AuthSchemeFactory> authSchemeRegistry) {
576 this.authSchemeRegistry = authSchemeRegistry;
577 return this;
578 }
579
580
581
582
583
584
585 public final HttpAsyncClientBuilder setDefaultCookieSpecRegistry(final Lookup<CookieSpecFactory> cookieSpecRegistry) {
586 this.cookieSpecRegistry = cookieSpecRegistry;
587 return this;
588 }
589
590
591
592
593
594 public final HttpAsyncClientBuilder setDefaultCookieStore(final CookieStore cookieStore) {
595 this.cookieStore = cookieStore;
596 return this;
597 }
598
599
600
601
602
603
604 public final HttpAsyncClientBuilder setDefaultRequestConfig(final RequestConfig config) {
605 this.defaultRequestConfig = config;
606 return this;
607 }
608
609
610
611
612
613 public final HttpAsyncClientBuilder useSystemProperties() {
614 this.systemProperties = true;
615 return this;
616 }
617
618
619
620
621 public final HttpAsyncClientBuilder disableConnectionState() {
622 connectionStateDisabled = true;
623 return this;
624 }
625
626
627
628
629 public final HttpAsyncClientBuilder disableRedirectHandling() {
630 redirectHandlingDisabled = true;
631 return this;
632 }
633
634
635
636
637 public final HttpAsyncClientBuilder disableAutomaticRetries() {
638 automaticRetriesDisabled = true;
639 return this;
640 }
641
642
643
644
645 public final HttpAsyncClientBuilder disableCookieManagement() {
646 this.cookieManagementDisabled = true;
647 return this;
648 }
649
650
651
652
653 public final HttpAsyncClientBuilder disableAuthCaching() {
654 this.authCachingDisabled = true;
655 return this;
656 }
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671 public final HttpAsyncClientBuilder evictExpiredConnections() {
672 evictExpiredConnections = true;
673 return this;
674 }
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693 public final HttpAsyncClientBuilder evictIdleConnections(final TimeValue maxIdleTime) {
694 this.evictIdleConnections = true;
695 this.maxIdleTime = maxIdleTime;
696 return this;
697 }
698
699
700
701
702
703
704 @Internal
705 protected void customizeExecChain(final NamedElementChain<AsyncExecChainHandler> execChainDefinition) {
706 }
707
708
709
710
711
712
713 @Internal
714 protected void addCloseable(final Closeable closeable) {
715 if (closeable == null) {
716 return;
717 }
718 if (closeables == null) {
719 closeables = new ArrayList<>();
720 }
721 closeables.add(closeable);
722 }
723
724 public CloseableHttpAsyncClient build() {
725 AsyncClientConnectionManager connManagerCopy = this.connManager;
726 if (connManagerCopy == null) {
727 connManagerCopy = PoolingAsyncClientConnectionManagerBuilder.create().build();
728 }
729
730 ConnectionKeepAliveStrategy keepAliveStrategyCopy = this.keepAliveStrategy;
731 if (keepAliveStrategyCopy == null) {
732 keepAliveStrategyCopy = DefaultConnectionKeepAliveStrategy.INSTANCE;
733 }
734
735 UserTokenHandler userTokenHandlerCopy = this.userTokenHandler;
736 if (userTokenHandlerCopy == null) {
737 if (!connectionStateDisabled) {
738 userTokenHandlerCopy = DefaultUserTokenHandler.INSTANCE;
739 } else {
740 userTokenHandlerCopy = NoopUserTokenHandler.INSTANCE;
741 }
742 }
743
744 final NamedElementChain<AsyncExecChainHandler> execChainDefinition = new NamedElementChain<>();
745 execChainDefinition.addLast(
746 new HttpAsyncMainClientExec(keepAliveStrategyCopy, userTokenHandlerCopy),
747 ChainElement.MAIN_TRANSPORT.name());
748
749 AuthenticationStrategy targetAuthStrategyCopy = this.targetAuthStrategy;
750 if (targetAuthStrategyCopy == null) {
751 targetAuthStrategyCopy = DefaultAuthenticationStrategy.INSTANCE;
752 }
753 AuthenticationStrategy proxyAuthStrategyCopy = this.proxyAuthStrategy;
754 if (proxyAuthStrategyCopy == null) {
755 proxyAuthStrategyCopy = DefaultAuthenticationStrategy.INSTANCE;
756 }
757
758 String userAgentCopy = this.userAgent;
759 if (userAgentCopy == null) {
760 if (systemProperties) {
761 userAgentCopy = getProperty("http.agent", null);
762 }
763 if (userAgentCopy == null) {
764 userAgentCopy = VersionInfo.getSoftwareInfo("Apache-HttpAsyncClient",
765 "org.apache.hc.client5", getClass());
766 }
767 }
768
769 execChainDefinition.addFirst(
770 new AsyncConnectExec(
771 new DefaultHttpProcessor(new RequestTargetHost(), new RequestUserAgent(userAgentCopy)),
772 proxyAuthStrategyCopy),
773 ChainElement.CONNECT.name());
774
775 final HttpProcessorBuilder b = HttpProcessorBuilder.create();
776 if (requestInterceptors != null) {
777 for (final RequestInterceptorEntry entry: requestInterceptors) {
778 if (entry.postion == RequestInterceptorEntry.Postion.FIRST) {
779 b.addFirst(entry.interceptor);
780 }
781 }
782 }
783 if (responseInterceptors != null) {
784 for (final ResponseInterceptorEntry entry: responseInterceptors) {
785 if (entry.postion == ResponseInterceptorEntry.Postion.FIRST) {
786 b.addFirst(entry.interceptor);
787 }
788 }
789 }
790 b.addAll(
791 new RequestDefaultHeaders(defaultHeaders),
792 new RequestUserAgent(userAgentCopy),
793 new RequestExpectContinue());
794 if (!cookieManagementDisabled) {
795 b.add(new RequestAddCookies());
796 }
797 if (!authCachingDisabled) {
798 b.add(new RequestAuthCache());
799 }
800 if (!cookieManagementDisabled) {
801 b.add(new ResponseProcessCookies());
802 }
803 if (requestInterceptors != null) {
804 for (final RequestInterceptorEntry entry: requestInterceptors) {
805 if (entry.postion == RequestInterceptorEntry.Postion.LAST) {
806 b.addLast(entry.interceptor);
807 }
808 }
809 }
810 if (responseInterceptors != null) {
811 for (final ResponseInterceptorEntry entry: responseInterceptors) {
812 if (entry.postion == ResponseInterceptorEntry.Postion.LAST) {
813 b.addLast(entry.interceptor);
814 }
815 }
816 }
817
818 final HttpProcessor httpProcessor = b.build();
819 execChainDefinition.addFirst(
820 new AsyncProtocolExec(httpProcessor, targetAuthStrategyCopy, proxyAuthStrategyCopy),
821 ChainElement.PROTOCOL.name());
822
823
824 if (!automaticRetriesDisabled) {
825 HttpRequestRetryStrategy retryStrategyCopy = this.retryStrategy;
826 if (retryStrategyCopy == null) {
827 retryStrategyCopy = DefaultHttpRequestRetryStrategy.INSTANCE;
828 }
829 execChainDefinition.addFirst(
830 new AsyncHttpRequestRetryExec(retryStrategyCopy),
831 ChainElement.RETRY.name());
832 }
833
834 HttpRoutePlanner routePlannerCopy = this.routePlanner;
835 if (routePlannerCopy == null) {
836 SchemePortResolver schemePortResolverCopy = this.schemePortResolver;
837 if (schemePortResolverCopy == null) {
838 schemePortResolverCopy = DefaultSchemePortResolver.INSTANCE;
839 }
840 if (proxy != null) {
841 routePlannerCopy = new DefaultProxyRoutePlanner(proxy, schemePortResolverCopy);
842 } else if (systemProperties) {
843 final ProxySelector defaultProxySelector = AccessController.doPrivileged(new PrivilegedAction<ProxySelector>() {
844 @Override
845 public ProxySelector run() {
846 return ProxySelector.getDefault();
847 }
848 });
849 routePlannerCopy = new SystemDefaultRoutePlanner(
850 schemePortResolverCopy, defaultProxySelector);
851 } else {
852 routePlannerCopy = new DefaultRoutePlanner(schemePortResolverCopy);
853 }
854 }
855
856
857 if (!redirectHandlingDisabled) {
858 RedirectStrategy redirectStrategyCopy = this.redirectStrategy;
859 if (redirectStrategyCopy == null) {
860 redirectStrategyCopy = DefaultRedirectStrategy.INSTANCE;
861 }
862 execChainDefinition.addFirst(
863 new AsyncRedirectExec(routePlannerCopy, redirectStrategyCopy),
864 ChainElement.REDIRECT.name());
865 }
866
867 List<Closeable> closeablesCopy = closeables != null ? new ArrayList<>(closeables) : null;
868 if (!this.connManagerShared) {
869 if (closeablesCopy == null) {
870 closeablesCopy = new ArrayList<>(1);
871 }
872 if (evictExpiredConnections || evictIdleConnections) {
873 if (connManagerCopy instanceof ConnPoolControl) {
874 final IdleConnectionEvictornEvictor.html#IdleConnectionEvictor">IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor((ConnPoolControl<?>) connManagerCopy,
875 maxIdleTime, maxIdleTime);
876 closeablesCopy.add(new Closeable() {
877
878 @Override
879 public void close() throws IOException {
880 connectionEvictor.shutdown();
881 }
882
883 });
884 connectionEvictor.start();
885 }
886 }
887 closeablesCopy.add(connManagerCopy);
888 }
889 ConnectionReuseStrategy reuseStrategyCopy = this.reuseStrategy;
890 if (reuseStrategyCopy == null) {
891 if (systemProperties) {
892 final String s = getProperty("http.keepAlive", "true");
893 if ("true".equalsIgnoreCase(s)) {
894 reuseStrategyCopy = DefaultConnectionReuseStrategy.INSTANCE;
895 } else {
896 reuseStrategyCopy = new ConnectionReuseStrategy() {
897 @Override
898 public boolean keepAlive(
899 final HttpRequest request, final HttpResponse response, final HttpContext context) {
900 return false;
901 }
902 };
903 }
904 } else {
905 reuseStrategyCopy = DefaultConnectionReuseStrategy.INSTANCE;
906 }
907 }
908 final AsyncPushConsumerRegistrymerRegistry.html#AsyncPushConsumerRegistry">AsyncPushConsumerRegistry pushConsumerRegistry = new AsyncPushConsumerRegistry();
909 final IOEventHandlerFactory ioEventHandlerFactory = new HttpAsyncClientEventHandlerFactory(
910 new DefaultHttpProcessor(new H2RequestContent(), new H2RequestTargetHost(), new H2RequestConnControl()),
911 new HandlerFactory<AsyncPushConsumer>() {
912
913 @Override
914 public AsyncPushConsumer create(final HttpRequest request, final HttpContext context) throws HttpException {
915 return pushConsumerRegistry.get(request);
916 }
917
918 },
919 versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE,
920 h2Config != null ? h2Config : H2Config.DEFAULT,
921 h1Config != null ? h1Config : Http1Config.DEFAULT,
922 charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
923 reuseStrategyCopy);
924 final DefaultConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(
925 ioEventHandlerFactory,
926 ioReactorConfig != null ? ioReactorConfig : IOReactorConfig.DEFAULT,
927 threadFactory != null ? threadFactory : new DefaultThreadFactory("httpclient-dispatch", true),
928 LoggingIOSessionDecorator.INSTANCE,
929 LoggingExceptionCallback.INSTANCE,
930 null,
931 new Callback<IOSession>() {
932
933 @Override
934 public void execute(final IOSession ioSession) {
935 ioSession.enqueue(new ShutdownCommand(CloseMode.GRACEFUL), Command.Priority.IMMEDIATE);
936 }
937
938 });
939
940 if (execInterceptors != null) {
941 for (final ExecInterceptorEntry entry: execInterceptors) {
942 switch (entry.postion) {
943 case AFTER:
944 execChainDefinition.addAfter(entry.existing, entry.interceptor, entry.name);
945 break;
946 case BEFORE:
947 execChainDefinition.addBefore(entry.existing, entry.interceptor, entry.name);
948 break;
949 case REPLACE:
950 execChainDefinition.replace(entry.existing, entry.interceptor);
951 break;
952 case FIRST:
953 execChainDefinition.addFirst(entry.interceptor, entry.name);
954 break;
955 case LAST:
956 execChainDefinition.addLast(entry.interceptor, entry.name);
957 break;
958 }
959 }
960 }
961
962 customizeExecChain(execChainDefinition);
963
964 NamedElementChain<AsyncExecChainHandler>.Node current = execChainDefinition.getLast();
965 AsyncExecChainElement execChain = null;
966 while (current != null) {
967 execChain = new AsyncExecChainElement(current.getValue(), execChain);
968 current = current.getPrevious();
969 }
970
971 Lookup<AuthSchemeFactory> authSchemeRegistryCopy = this.authSchemeRegistry;
972 if (authSchemeRegistryCopy == null) {
973 authSchemeRegistryCopy = RegistryBuilder.<AuthSchemeFactory>create()
974 .register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
975 .register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
976 .register(StandardAuthScheme.NTLM, NTLMSchemeFactory.INSTANCE)
977 .register(StandardAuthScheme.SPNEGO, SPNegoSchemeFactory.DEFAULT)
978 .register(StandardAuthScheme.KERBEROS, KerberosSchemeFactory.DEFAULT)
979 .build();
980 }
981 Lookup<CookieSpecFactory> cookieSpecRegistryCopy = this.cookieSpecRegistry;
982 if (cookieSpecRegistryCopy == null) {
983 cookieSpecRegistryCopy = CookieSpecSupport.createDefault();
984 }
985
986 CookieStore cookieStoreCopy = this.cookieStore;
987 if (cookieStoreCopy == null) {
988 cookieStoreCopy = new BasicCookieStore();
989 }
990
991 CredentialsProvider credentialsProviderCopy = this.credentialsProvider;
992 if (credentialsProviderCopy == null) {
993 if (systemProperties) {
994 credentialsProviderCopy = new SystemDefaultCredentialsProvider();
995 } else {
996 credentialsProviderCopy = new BasicCredentialsProvider();
997 }
998 }
999
1000 return new InternalHttpAsyncClient(
1001 ioReactor,
1002 execChain,
1003 pushConsumerRegistry,
1004 threadFactory != null ? threadFactory : new DefaultThreadFactory("httpclient-main", true),
1005 connManagerCopy,
1006 routePlannerCopy,
1007 versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE,
1008 cookieSpecRegistryCopy,
1009 authSchemeRegistryCopy,
1010 cookieStoreCopy,
1011 credentialsProviderCopy,
1012 defaultRequestConfig,
1013 closeablesCopy);
1014 }
1015
1016 private String getProperty(final String key, final String defaultValue) {
1017 return AccessController.doPrivileged(new PrivilegedAction<String>() {
1018 @Override
1019 public String run() {
1020 return System.getProperty(key, defaultValue);
1021 }
1022 });
1023 }
1024
1025 }