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