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.http.impl.client;
29  
30  import java.io.Closeable;
31  import java.io.IOException;
32  import java.net.ProxySelector;
33  import java.util.ArrayList;
34  import java.util.Collection;
35  import java.util.Collections;
36  import java.util.LinkedList;
37  import java.util.List;
38  import java.util.Map;
39  import java.util.concurrent.TimeUnit;
40  
41  import javax.net.ssl.HostnameVerifier;
42  import javax.net.ssl.SSLContext;
43  import javax.net.ssl.SSLSocketFactory;
44  
45  import org.apache.http.ConnectionReuseStrategy;
46  import org.apache.http.Header;
47  import org.apache.http.HttpHost;
48  import org.apache.http.HttpRequestInterceptor;
49  import org.apache.http.HttpResponseInterceptor;
50  import org.apache.http.auth.AuthSchemeProvider;
51  import org.apache.http.client.AuthenticationStrategy;
52  import org.apache.http.client.BackoffManager;
53  import org.apache.http.client.ConnectionBackoffStrategy;
54  import org.apache.http.client.CookieStore;
55  import org.apache.http.client.CredentialsProvider;
56  import org.apache.http.client.HttpRequestRetryHandler;
57  import org.apache.http.client.RedirectStrategy;
58  import org.apache.http.client.ServiceUnavailableRetryStrategy;
59  import org.apache.http.client.UserTokenHandler;
60  import org.apache.http.client.config.AuthSchemes;
61  import org.apache.http.client.config.RequestConfig;
62  import org.apache.http.client.entity.InputStreamFactory;
63  import org.apache.http.client.protocol.RequestAcceptEncoding;
64  import org.apache.http.client.protocol.RequestAddCookies;
65  import org.apache.http.client.protocol.RequestAuthCache;
66  import org.apache.http.client.protocol.RequestClientConnControl;
67  import org.apache.http.client.protocol.RequestDefaultHeaders;
68  import org.apache.http.client.protocol.RequestExpectContinue;
69  import org.apache.http.client.protocol.ResponseContentEncoding;
70  import org.apache.http.client.protocol.ResponseProcessCookies;
71  import org.apache.http.config.ConnectionConfig;
72  import org.apache.http.config.Lookup;
73  import org.apache.http.config.RegistryBuilder;
74  import org.apache.http.config.SocketConfig;
75  import org.apache.http.conn.ConnectionKeepAliveStrategy;
76  import org.apache.http.conn.DnsResolver;
77  import org.apache.http.conn.HttpClientConnectionManager;
78  import org.apache.http.conn.SchemePortResolver;
79  import org.apache.http.conn.routing.HttpRoutePlanner;
80  import org.apache.http.conn.socket.ConnectionSocketFactory;
81  import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
82  import org.apache.http.conn.socket.PlainConnectionSocketFactory;
83  import org.apache.http.conn.ssl.DefaultHostnameVerifier;
84  import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
85  import org.apache.http.conn.ssl.X509HostnameVerifier;
86  import org.apache.http.conn.util.PublicSuffixMatcher;
87  import org.apache.http.conn.util.PublicSuffixMatcherLoader;
88  import org.apache.http.cookie.CookieSpecProvider;
89  import org.apache.http.impl.NoConnectionReuseStrategy;
90  import org.apache.http.impl.auth.BasicSchemeFactory;
91  import org.apache.http.impl.auth.DigestSchemeFactory;
92  import org.apache.http.impl.auth.KerberosSchemeFactory;
93  import org.apache.http.impl.auth.NTLMSchemeFactory;
94  import org.apache.http.impl.auth.SPNegoSchemeFactory;
95  import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
96  import org.apache.http.impl.conn.DefaultRoutePlanner;
97  import org.apache.http.impl.conn.DefaultSchemePortResolver;
98  import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
99  import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
100 import org.apache.http.impl.execchain.BackoffStrategyExec;
101 import org.apache.http.impl.execchain.ClientExecChain;
102 import org.apache.http.impl.execchain.MainClientExec;
103 import org.apache.http.impl.execchain.ProtocolExec;
104 import org.apache.http.impl.execchain.RedirectExec;
105 import org.apache.http.impl.execchain.RetryExec;
106 import org.apache.http.impl.execchain.ServiceUnavailableRetryExec;
107 import org.apache.http.protocol.HttpProcessor;
108 import org.apache.http.protocol.HttpProcessorBuilder;
109 import org.apache.http.protocol.HttpRequestExecutor;
110 import org.apache.http.protocol.ImmutableHttpProcessor;
111 import org.apache.http.protocol.RequestContent;
112 import org.apache.http.protocol.RequestTargetHost;
113 import org.apache.http.protocol.RequestUserAgent;
114 import org.apache.http.ssl.SSLContexts;
115 import org.apache.http.util.TextUtils;
116 import org.apache.http.util.VersionInfo;
117 
118 /**
119  * Builder for {@link CloseableHttpClient} instances.
120  * <p>
121  * When a particular component is not explicitly set this class will
122  * use its default implementation. System properties will be taken
123  * into account when configuring the default implementations when
124  * {@link #useSystemProperties()} method is called prior to calling
125  * {@link #build()}.
126  * </p>
127  * <ul>
128  *  <li>ssl.TrustManagerFactory.algorithm</li>
129  *  <li>javax.net.ssl.trustStoreType</li>
130  *  <li>javax.net.ssl.trustStore</li>
131  *  <li>javax.net.ssl.trustStoreProvider</li>
132  *  <li>javax.net.ssl.trustStorePassword</li>
133  *  <li>ssl.KeyManagerFactory.algorithm</li>
134  *  <li>javax.net.ssl.keyStoreType</li>
135  *  <li>javax.net.ssl.keyStore</li>
136  *  <li>javax.net.ssl.keyStoreProvider</li>
137  *  <li>javax.net.ssl.keyStorePassword</li>
138  *  <li>https.protocols</li>
139  *  <li>https.cipherSuites</li>
140  *  <li>http.proxyHost</li>
141  *  <li>http.proxyPort</li>
142  *  <li>https.proxyHost</li>
143  *  <li>https.proxyPort</li>
144  *  <li>http.nonProxyHosts</li>
145  *  <li>https.proxyUser</li>
146  *  <li>http.proxyUser</li>
147  *  <li>https.proxyPassword</li>
148  *  <li>http.proxyPassword</li>
149  *  <li>http.keepAlive</li>
150  *  <li>http.maxConnections</li>
151  *  <li>http.agent</li>
152  * </ul>
153  * <p>
154  * Please note that some settings used by this class can be mutually
155  * exclusive and may not apply when building {@link CloseableHttpClient}
156  * instances.
157  * </p>
158  *
159  * @since 4.3
160  */
161 public class HttpClientBuilder {
162 
163     private HttpRequestExecutor requestExec;
164     private HostnameVerifier hostnameVerifier;
165     private LayeredConnectionSocketFactory sslSocketFactory;
166     private SSLContext sslContext;
167     private HttpClientConnectionManager connManager;
168     private boolean connManagerShared;
169     private SchemePortResolver schemePortResolver;
170     private ConnectionReuseStrategy reuseStrategy;
171     private ConnectionKeepAliveStrategy keepAliveStrategy;
172     private AuthenticationStrategy targetAuthStrategy;
173     private AuthenticationStrategy proxyAuthStrategy;
174     private UserTokenHandler userTokenHandler;
175     private HttpProcessor httpprocessor;
176     private DnsResolver dnsResolver;
177 
178     private LinkedList<HttpRequestInterceptor> requestFirst;
179     private LinkedList<HttpRequestInterceptor> requestLast;
180     private LinkedList<HttpResponseInterceptor> responseFirst;
181     private LinkedList<HttpResponseInterceptor> responseLast;
182 
183     private HttpRequestRetryHandler retryHandler;
184     private HttpRoutePlanner routePlanner;
185     private RedirectStrategy redirectStrategy;
186     private ConnectionBackoffStrategy connectionBackoffStrategy;
187     private BackoffManager backoffManager;
188     private ServiceUnavailableRetryStrategy serviceUnavailStrategy;
189     private Lookup<AuthSchemeProvider> authSchemeRegistry;
190     private Lookup<CookieSpecProvider> cookieSpecRegistry;
191     private Map<String, InputStreamFactory> contentDecoderMap;
192     private CookieStore cookieStore;
193     private CredentialsProvider credentialsProvider;
194     private String userAgent;
195     private HttpHost proxy;
196     private Collection<? extends Header> defaultHeaders;
197     private SocketConfig defaultSocketConfig;
198     private ConnectionConfig defaultConnectionConfig;
199     private RequestConfig defaultRequestConfig;
200     private boolean evictExpiredConnections;
201     private boolean evictIdleConnections;
202     private long maxIdleTime;
203     private TimeUnit maxIdleTimeUnit;
204 
205     private boolean systemProperties;
206     private boolean redirectHandlingDisabled;
207     private boolean automaticRetriesDisabled;
208     private boolean contentCompressionDisabled;
209     private boolean cookieManagementDisabled;
210     private boolean authCachingDisabled;
211     private boolean connectionStateDisabled;
212     private boolean defaultUserAgentDisabled;
213 
214     private int maxConnTotal = 0;
215     private int maxConnPerRoute = 0;
216 
217     private long connTimeToLive = -1;
218     private TimeUnit connTimeToLiveTimeUnit = TimeUnit.MILLISECONDS;
219 
220     private List<Closeable> closeables;
221 
222     private PublicSuffixMatcher publicSuffixMatcher;
223 
224     public static HttpClientBuilder create() {
225         return new HttpClientBuilder();
226     }
227 
228     protected HttpClientBuilder() {
229         super();
230     }
231 
232     /**
233      * Assigns {@link HttpRequestExecutor} instance.
234      */
235     public final HttpClientBuilder setRequestExecutor(final HttpRequestExecutor requestExec) {
236         this.requestExec = requestExec;
237         return this;
238     }
239 
240     /**
241      * Assigns {@link X509HostnameVerifier} instance.
242      * <p>
243      * Please note this value can be overridden by the {@link #setConnectionManager(
244      *   org.apache.http.conn.HttpClientConnectionManager)} and the {@link #setSSLSocketFactory(
245      *   org.apache.http.conn.socket.LayeredConnectionSocketFactory)} methods.
246      * </p>
247      *
248      *   @deprecated (4.4)
249      */
250     @Deprecated
251     public final HttpClientBuilder setHostnameVerifier(final X509HostnameVerifier hostnameVerifier) {
252         this.hostnameVerifier = hostnameVerifier;
253         return this;
254     }
255 
256     /**
257      * Assigns {@link javax.net.ssl.HostnameVerifier} instance.
258      * <p>
259      * Please note this value can be overridden by the {@link #setConnectionManager(
260      *   org.apache.http.conn.HttpClientConnectionManager)} and the {@link #setSSLSocketFactory(
261      *   org.apache.http.conn.socket.LayeredConnectionSocketFactory)} methods.
262      * </p>
263      *
264      *   @since 4.4
265      */
266     public final HttpClientBuilder setSSLHostnameVerifier(final HostnameVerifier hostnameVerifier) {
267         this.hostnameVerifier = hostnameVerifier;
268         return this;
269     }
270 
271     /**
272      * Assigns file containing public suffix matcher. Instances of this class can be created
273      * with {@link org.apache.http.conn.util.PublicSuffixMatcherLoader}.
274      *
275      * @see org.apache.http.conn.util.PublicSuffixMatcher
276      * @see org.apache.http.conn.util.PublicSuffixMatcherLoader
277      *
278      *   @since 4.4
279      */
280     public final HttpClientBuilder setPublicSuffixMatcher(final PublicSuffixMatcher publicSuffixMatcher) {
281         this.publicSuffixMatcher = publicSuffixMatcher;
282         return this;
283     }
284 
285     /**
286      * Assigns {@link SSLContext} instance.
287      * <p>
288      * Please note this value can be overridden by the {@link #setConnectionManager(
289      *   org.apache.http.conn.HttpClientConnectionManager)} and the {@link #setSSLSocketFactory(
290      *   org.apache.http.conn.socket.LayeredConnectionSocketFactory)} methods.
291      * </p>
292      *
293      * @deprecated (4.5) use {@link #setSSLContext(SSLContext)}
294      */
295     @Deprecated
296     public final HttpClientBuilder setSslcontext(final SSLContext sslcontext) {
297         return setSSLContext(sslcontext);
298     }
299 
300     /**
301      * Assigns {@link SSLContext} instance.
302      * <p>
303      * Please note this value can be overridden by the {@link #setConnectionManager(
304      *   org.apache.http.conn.HttpClientConnectionManager)} and the {@link #setSSLSocketFactory(
305      *   org.apache.http.conn.socket.LayeredConnectionSocketFactory)} methods.
306      * </p>
307      */
308     public final HttpClientBuilder setSSLContext(final SSLContext sslContext) {
309         this.sslContext = sslContext;
310         return this;
311     }
312 
313     /**
314      * Assigns {@link LayeredConnectionSocketFactory} instance.
315      * <p>
316      * Please note this value can be overridden by the {@link #setConnectionManager(
317      *   org.apache.http.conn.HttpClientConnectionManager)} method.
318      * </p>
319      */
320     public final HttpClientBuilder setSSLSocketFactory(
321             final LayeredConnectionSocketFactory sslSocketFactory) {
322         this.sslSocketFactory = sslSocketFactory;
323         return this;
324     }
325 
326     /**
327      * Assigns maximum total connection value.
328      * <p>
329      * Please note this value can be overridden by the {@link #setConnectionManager(
330      *   org.apache.http.conn.HttpClientConnectionManager)} method.
331      * </p>
332      */
333     public final HttpClientBuilder setMaxConnTotal(final int maxConnTotal) {
334         this.maxConnTotal = maxConnTotal;
335         return this;
336     }
337 
338     /**
339      * Assigns maximum connection per route value.
340      * <p>
341      * Please note this value can be overridden by the {@link #setConnectionManager(
342      *   org.apache.http.conn.HttpClientConnectionManager)} method.
343      * </p>
344      */
345     public final HttpClientBuilder setMaxConnPerRoute(final int maxConnPerRoute) {
346         this.maxConnPerRoute = maxConnPerRoute;
347         return this;
348     }
349 
350     /**
351      * Assigns default {@link SocketConfig}.
352      * <p>
353      * Please note this value can be overridden by the {@link #setConnectionManager(
354      *   org.apache.http.conn.HttpClientConnectionManager)} method.
355      * </p>
356      */
357     public final HttpClientBuilder setDefaultSocketConfig(final SocketConfig config) {
358         this.defaultSocketConfig = config;
359         return this;
360     }
361 
362     /**
363      * Assigns default {@link ConnectionConfig}.
364      * <p>
365      * Please note this value can be overridden by the {@link #setConnectionManager(
366      *   org.apache.http.conn.HttpClientConnectionManager)} method.
367      * </p>
368      */
369     public final HttpClientBuilder setDefaultConnectionConfig(final ConnectionConfig config) {
370         this.defaultConnectionConfig = config;
371         return this;
372     }
373 
374     /**
375      * Sets maximum time to live for persistent connections
376      * <p>
377      * Please note this value can be overridden by the {@link #setConnectionManager(
378      *   org.apache.http.conn.HttpClientConnectionManager)} method.
379      * </p>
380      *
381      * @since 4.4
382      */
383     public final HttpClientBuilder setConnectionTimeToLive(final long connTimeToLive, final TimeUnit connTimeToLiveTimeUnit) {
384         this.connTimeToLive = connTimeToLive;
385         this.connTimeToLiveTimeUnit = connTimeToLiveTimeUnit;
386         return this;
387     }
388 
389     /**
390      * Assigns {@link HttpClientConnectionManager} instance.
391      */
392     public final HttpClientBuilder setConnectionManager(
393             final HttpClientConnectionManager connManager) {
394         this.connManager = connManager;
395         return this;
396     }
397 
398     /**
399      * Defines the connection manager is to be shared by multiple
400      * client instances.
401      * <p>
402      * If the connection manager is shared its life-cycle is expected
403      * to be managed by the caller and it will not be shut down
404      * if the client is closed.
405      * </p>
406      *
407      * @param shared defines whether or not the connection manager can be shared
408      *  by multiple clients.
409      *
410      * @since 4.4
411      */
412     public final HttpClientBuilder setConnectionManagerShared(
413             final boolean shared) {
414         this.connManagerShared = shared;
415         return this;
416     }
417 
418     /**
419      * Assigns {@link ConnectionReuseStrategy} instance.
420      */
421     public final HttpClientBuilder setConnectionReuseStrategy(
422             final ConnectionReuseStrategy reuseStrategy) {
423         this.reuseStrategy = reuseStrategy;
424         return this;
425     }
426 
427     /**
428      * Assigns {@link ConnectionKeepAliveStrategy} instance.
429      */
430     public final HttpClientBuilder setKeepAliveStrategy(
431             final ConnectionKeepAliveStrategy keepAliveStrategy) {
432         this.keepAliveStrategy = keepAliveStrategy;
433         return this;
434     }
435 
436     /**
437      * Assigns {@link AuthenticationStrategy} instance for target
438      * host authentication.
439      */
440     public final HttpClientBuilder setTargetAuthenticationStrategy(
441             final AuthenticationStrategy targetAuthStrategy) {
442         this.targetAuthStrategy = targetAuthStrategy;
443         return this;
444     }
445 
446     /**
447      * Assigns {@link AuthenticationStrategy} instance for proxy
448      * authentication.
449      */
450     public final HttpClientBuilder setProxyAuthenticationStrategy(
451             final AuthenticationStrategy proxyAuthStrategy) {
452         this.proxyAuthStrategy = proxyAuthStrategy;
453         return this;
454     }
455 
456     /**
457      * Assigns {@link UserTokenHandler} instance.
458      * <p>
459      * Please note this value can be overridden by the {@link #disableConnectionState()}
460      * method.
461      * </p>
462      */
463     public final HttpClientBuilder setUserTokenHandler(final UserTokenHandler userTokenHandler) {
464         this.userTokenHandler = userTokenHandler;
465         return this;
466     }
467 
468     /**
469      * Disables connection state tracking.
470      */
471     public final HttpClientBuilder disableConnectionState() {
472         connectionStateDisabled = true;
473         return this;
474     }
475 
476     /**
477      * Assigns {@link SchemePortResolver} instance.
478      */
479     public final HttpClientBuilder setSchemePortResolver(
480             final SchemePortResolver schemePortResolver) {
481         this.schemePortResolver = schemePortResolver;
482         return this;
483     }
484 
485     /**
486      * Assigns {@code User-Agent} value.
487      * <p>
488      * Please note this value can be overridden by the {@link #setHttpProcessor(
489      * org.apache.http.protocol.HttpProcessor)} method.
490      * </p>
491      */
492     public final HttpClientBuilder setUserAgent(final String userAgent) {
493         this.userAgent = userAgent;
494         return this;
495     }
496 
497     /**
498      * Assigns default request header values.
499      * <p>
500      * Please note this value can be overridden by the {@link #setHttpProcessor(
501      * org.apache.http.protocol.HttpProcessor)} method.
502      * </p>
503      */
504     public final HttpClientBuilder setDefaultHeaders(final Collection<? extends Header> defaultHeaders) {
505         this.defaultHeaders = defaultHeaders;
506         return this;
507     }
508 
509     /**
510      * Adds this protocol interceptor to the head of the protocol processing list.
511      * <p>
512      * Please note this value can be overridden by the {@link #setHttpProcessor(
513      * org.apache.http.protocol.HttpProcessor)} method.
514      * </p>
515      */
516     public final HttpClientBuilder addInterceptorFirst(final HttpResponseInterceptor itcp) {
517         if (itcp == null) {
518             return this;
519         }
520         if (responseFirst == null) {
521             responseFirst = new LinkedList<HttpResponseInterceptor>();
522         }
523         responseFirst.addFirst(itcp);
524         return this;
525     }
526 
527     /**
528      * Adds this protocol interceptor to the tail of the protocol processing list.
529      * <p>
530      * Please note this value can be overridden by the {@link #setHttpProcessor(
531      * org.apache.http.protocol.HttpProcessor)} method.
532      * </p>
533      */
534     public final HttpClientBuilder addInterceptorLast(final HttpResponseInterceptor itcp) {
535         if (itcp == null) {
536             return this;
537         }
538         if (responseLast == null) {
539             responseLast = new LinkedList<HttpResponseInterceptor>();
540         }
541         responseLast.addLast(itcp);
542         return this;
543     }
544 
545     /**
546      * Adds this protocol interceptor to the head of the protocol processing list.
547      * <p>
548      * Please note this value can be overridden by the {@link #setHttpProcessor(
549      * org.apache.http.protocol.HttpProcessor)} method.
550      */
551     public final HttpClientBuilder addInterceptorFirst(final HttpRequestInterceptor itcp) {
552         if (itcp == null) {
553             return this;
554         }
555         if (requestFirst == null) {
556             requestFirst = new LinkedList<HttpRequestInterceptor>();
557         }
558         requestFirst.addFirst(itcp);
559         return this;
560     }
561 
562     /**
563      * Adds this protocol interceptor to the tail of the protocol processing list.
564      * <p>
565      * Please note this value can be overridden by the {@link #setHttpProcessor(
566      * org.apache.http.protocol.HttpProcessor)} method.
567      */
568     public final HttpClientBuilder addInterceptorLast(final HttpRequestInterceptor itcp) {
569         if (itcp == null) {
570             return this;
571         }
572         if (requestLast == null) {
573             requestLast = new LinkedList<HttpRequestInterceptor>();
574         }
575         requestLast.addLast(itcp);
576         return this;
577     }
578 
579     /**
580      * Disables state (cookie) management.
581      * <p>
582      * Please note this value can be overridden by the {@link #setHttpProcessor(
583      * org.apache.http.protocol.HttpProcessor)} method.
584      */
585     public final HttpClientBuilder disableCookieManagement() {
586         this.cookieManagementDisabled = true;
587         return this;
588     }
589 
590     /**
591      * Disables automatic content decompression.
592      * <p>
593      * Please note this value can be overridden by the {@link #setHttpProcessor(
594      * org.apache.http.protocol.HttpProcessor)} method.
595      */
596     public final HttpClientBuilder disableContentCompression() {
597         contentCompressionDisabled = true;
598         return this;
599     }
600 
601     /**
602      * Disables authentication scheme caching.
603      * <p>
604      * Please note this value can be overridden by the {@link #setHttpProcessor(
605      * org.apache.http.protocol.HttpProcessor)} method.
606      */
607     public final HttpClientBuilder disableAuthCaching() {
608         this.authCachingDisabled = true;
609         return this;
610     }
611 
612     /**
613      * Assigns {@link HttpProcessor} instance.
614      */
615     public final HttpClientBuilder setHttpProcessor(final HttpProcessor httpprocessor) {
616         this.httpprocessor = httpprocessor;
617         return this;
618     }
619 
620     /**
621      * Assigns {@link DnsResolver} instance.
622      * <p>
623      * Please note this value can be overridden by the {@link #setConnectionManager(HttpClientConnectionManager)} method.
624      */
625     public final HttpClientBuilder setDnsResolver(final DnsResolver dnsResolver) {
626         this.dnsResolver = dnsResolver;
627         return this;
628     }
629 
630     /**
631      * Assigns {@link HttpRequestRetryHandler} instance.
632      * <p>
633      * Please note this value can be overridden by the {@link #disableAutomaticRetries()}
634      * method.
635      */
636     public final HttpClientBuilder setRetryHandler(final HttpRequestRetryHandler retryHandler) {
637         this.retryHandler = retryHandler;
638         return this;
639     }
640 
641     /**
642      * Disables automatic request recovery and re-execution.
643      */
644     public final HttpClientBuilder disableAutomaticRetries() {
645         automaticRetriesDisabled = true;
646         return this;
647     }
648 
649     /**
650      * Assigns default proxy value.
651      * <p>
652      * Please note this value can be overridden by the {@link #setRoutePlanner(
653      *   org.apache.http.conn.routing.HttpRoutePlanner)} method.
654      */
655     public final HttpClientBuilder setProxy(final HttpHost proxy) {
656         this.proxy = proxy;
657         return this;
658     }
659 
660     /**
661      * Assigns {@link HttpRoutePlanner} instance.
662      */
663     public final HttpClientBuilder setRoutePlanner(final HttpRoutePlanner routePlanner) {
664         this.routePlanner = routePlanner;
665         return this;
666     }
667 
668     /**
669      * Assigns {@link RedirectStrategy} instance.
670      * <p>
671      * Please note this value can be overridden by the {@link #disableRedirectHandling()}
672      * method.
673      * </p>
674 `     */
675     public final HttpClientBuilder setRedirectStrategy(final RedirectStrategy redirectStrategy) {
676         this.redirectStrategy = redirectStrategy;
677         return this;
678     }
679 
680     /**
681      * Disables automatic redirect handling.
682      */
683     public final HttpClientBuilder disableRedirectHandling() {
684         redirectHandlingDisabled = true;
685         return this;
686     }
687 
688     /**
689      * Assigns {@link ConnectionBackoffStrategy} instance.
690      */
691     public final HttpClientBuilder setConnectionBackoffStrategy(
692             final ConnectionBackoffStrategy connectionBackoffStrategy) {
693         this.connectionBackoffStrategy = connectionBackoffStrategy;
694         return this;
695     }
696 
697     /**
698      * Assigns {@link BackoffManager} instance.
699      */
700     public final HttpClientBuilder setBackoffManager(final BackoffManager backoffManager) {
701         this.backoffManager = backoffManager;
702         return this;
703     }
704 
705     /**
706      * Assigns {@link ServiceUnavailableRetryStrategy} instance.
707      */
708     public final HttpClientBuilder setServiceUnavailableRetryStrategy(
709             final ServiceUnavailableRetryStrategy serviceUnavailStrategy) {
710         this.serviceUnavailStrategy = serviceUnavailStrategy;
711         return this;
712     }
713 
714     /**
715      * Assigns default {@link CookieStore} instance which will be used for
716      * request execution if not explicitly set in the client execution context.
717      */
718     public final HttpClientBuilder setDefaultCookieStore(final CookieStore cookieStore) {
719         this.cookieStore = cookieStore;
720         return this;
721     }
722 
723     /**
724      * Assigns default {@link CredentialsProvider} instance which will be used
725      * for request execution if not explicitly set in the client execution
726      * context.
727      */
728     public final HttpClientBuilder setDefaultCredentialsProvider(
729             final CredentialsProvider credentialsProvider) {
730         this.credentialsProvider = credentialsProvider;
731         return this;
732     }
733 
734     /**
735      * Assigns default {@link org.apache.http.auth.AuthScheme} registry which will
736      * be used for request execution if not explicitly set in the client execution
737      * context.
738      */
739     public final HttpClientBuilder setDefaultAuthSchemeRegistry(
740             final Lookup<AuthSchemeProvider> authSchemeRegistry) {
741         this.authSchemeRegistry = authSchemeRegistry;
742         return this;
743     }
744 
745     /**
746      * Assigns default {@link org.apache.http.cookie.CookieSpec} registry which will
747      * be used for request execution if not explicitly set in the client execution
748      * context.
749      *
750      * @see org.apache.http.impl.client.CookieSpecRegistries
751      *
752      */
753     public final HttpClientBuilder setDefaultCookieSpecRegistry(
754             final Lookup<CookieSpecProvider> cookieSpecRegistry) {
755         this.cookieSpecRegistry = cookieSpecRegistry;
756         return this;
757     }
758 
759 
760     /**
761      * Assigns a map of {@link org.apache.http.client.entity.InputStreamFactory}s
762      * to be used for automatic content decompression.
763      */
764     public final HttpClientBuilder setContentDecoderRegistry(
765             final Map<String, InputStreamFactory> contentDecoderMap) {
766         this.contentDecoderMap = contentDecoderMap;
767         return this;
768     }
769 
770     /**
771      * Assigns default {@link RequestConfig} instance which will be used
772      * for request execution if not explicitly set in the client execution
773      * context.
774      */
775     public final HttpClientBuilder setDefaultRequestConfig(final RequestConfig config) {
776         this.defaultRequestConfig = config;
777         return this;
778     }
779 
780     /**
781      * Use system properties when creating and configuring default
782      * implementations.
783      */
784     public final HttpClientBuilder useSystemProperties() {
785         this.systemProperties = true;
786         return this;
787     }
788 
789     /**
790      * Makes this instance of HttpClient proactively evict expired connections from the
791      * connection pool using a background thread.
792      * <p>
793      * One MUST explicitly close HttpClient with {@link CloseableHttpClient#close()} in order
794      * to stop and release the background thread.
795      * <p>
796      * Please note this method has no effect if the instance of HttpClient is configuted to
797      * use a shared connection manager.
798      * <p>
799      * Please note this method may not be used when the instance of HttpClient is created
800      * inside an EJB container.
801      *
802      * @see #setConnectionManagerShared(boolean)
803      * @see org.apache.http.conn.HttpClientConnectionManager#closeExpiredConnections()
804      *
805      * @since 4.4
806      */
807     public final HttpClientBuilder evictExpiredConnections() {
808         evictExpiredConnections = true;
809         return this;
810     }
811 
812     /**
813      * Makes this instance of HttpClient proactively evict idle connections from the
814      * connection pool using a background thread.
815      * <p>
816      * One MUST explicitly close HttpClient with {@link CloseableHttpClient#close()} in order
817      * to stop and release the background thread.
818      * <p>
819      * Please note this method has no effect if the instance of HttpClient is configuted to
820      * use a shared connection manager.
821      * <p>
822      * Please note this method may not be used when the instance of HttpClient is created
823      * inside an EJB container.
824      *
825      * @see #setConnectionManagerShared(boolean)
826      * @see org.apache.http.conn.HttpClientConnectionManager#closeExpiredConnections()
827      *
828      * @param maxIdleTime maximum time persistent connections can stay idle while kept alive
829      * in the connection pool. Connections whose inactivity period exceeds this value will
830      * get closed and evicted from the pool.
831      * @param maxIdleTimeUnit time unit for the above parameter.
832      *
833      * @deprecated (4.5) use {@link #evictIdleConnections(long, TimeUnit)}
834      *
835      * @since 4.4
836      */
837     @Deprecated
838     public final HttpClientBuilder evictIdleConnections(final Long maxIdleTime, final TimeUnit maxIdleTimeUnit) {
839         return evictIdleConnections(maxIdleTime.longValue(), maxIdleTimeUnit);
840     }
841 
842     /**
843      * Makes this instance of HttpClient proactively evict idle connections from the
844      * connection pool using a background thread.
845      * <p>
846      * One MUST explicitly close HttpClient with {@link CloseableHttpClient#close()} in order
847      * to stop and release the background thread.
848      * <p>
849      * Please note this method has no effect if the instance of HttpClient is configuted to
850      * use a shared connection manager.
851      * <p>
852      * Please note this method may not be used when the instance of HttpClient is created
853      * inside an EJB container.
854      *
855      * @see #setConnectionManagerShared(boolean)
856      * @see org.apache.http.conn.HttpClientConnectionManager#closeExpiredConnections()
857      *
858      * @param maxIdleTime maximum time persistent connections can stay idle while kept alive
859      * in the connection pool. Connections whose inactivity period exceeds this value will
860      * get closed and evicted from the pool.
861      * @param maxIdleTimeUnit time unit for the above parameter.
862      *
863      * @since 4.4
864      */
865     public final HttpClientBuilder evictIdleConnections(final long maxIdleTime, final TimeUnit maxIdleTimeUnit) {
866         this.evictIdleConnections = true;
867         this.maxIdleTime = maxIdleTime;
868         this.maxIdleTimeUnit = maxIdleTimeUnit;
869         return this;
870     }
871 
872     /**
873      * Disables the default user agent set by this builder if none has been provided by the user.
874      *
875      * @since 4.5.7
876      */
877     public final HttpClientBuilder disableDefaultUserAgent() {
878         this.defaultUserAgentDisabled = true;
879         return this;
880     }
881 
882     /**
883      * Produces an instance of {@link ClientExecChain} to be used as a main exec.
884      * <p>
885      * Default implementation produces an instance of {@link MainClientExec}
886      * </p>
887      * <p>
888      * For internal use.
889      * </p>
890      *
891      * @since 4.4
892      */
893     protected ClientExecChain createMainExec(
894             final HttpRequestExecutor requestExec,
895             final HttpClientConnectionManager connManager,
896             final ConnectionReuseStrategy reuseStrategy,
897             final ConnectionKeepAliveStrategy keepAliveStrategy,
898             final HttpProcessor proxyHttpProcessor,
899             final AuthenticationStrategy targetAuthStrategy,
900             final AuthenticationStrategy proxyAuthStrategy,
901             final UserTokenHandler userTokenHandler)
902     {
903         return new MainClientExec(
904                 requestExec,
905                 connManager,
906                 reuseStrategy,
907                 keepAliveStrategy,
908                 proxyHttpProcessor,
909                 targetAuthStrategy,
910                 proxyAuthStrategy,
911                 userTokenHandler);
912     }
913 
914     /**
915      * For internal use.
916      */
917     protected ClientExecChainin.html#ClientExecChain">ClientExecChain decorateMainExec(final ClientExecChain mainExec) {
918         return mainExec;
919     }
920 
921     /**
922      * For internal use.
923      */
924     protected ClientExecChaintml#ClientExecChain">ClientExecChain decorateProtocolExec(final ClientExecChain protocolExec) {
925         return protocolExec;
926     }
927 
928     /**
929      * For internal use.
930      */
931     protected void addCloseable(final Closeable closeable) {
932         if (closeable == null) {
933             return;
934         }
935         if (closeables == null) {
936             closeables = new ArrayList<Closeable>();
937         }
938         closeables.add(closeable);
939     }
940 
941     private static String[] split(final String s) {
942         if (TextUtils.isBlank(s)) {
943             return null;
944         }
945         return s.split(" *, *");
946     }
947 
948     public CloseableHttpClient build() {
949         // Create main request executor
950         // We copy the instance fields to avoid changing them, and rename to avoid accidental use of the wrong version
951         PublicSuffixMatcher publicSuffixMatcherCopy = this.publicSuffixMatcher;
952         if (publicSuffixMatcherCopy == null) {
953             publicSuffixMatcherCopy = PublicSuffixMatcherLoader.getDefault();
954         }
955 
956         HttpRequestExecutor requestExecCopy = this.requestExec;
957         if (requestExecCopy == null) {
958             requestExecCopy = new HttpRequestExecutor();
959         }
960         HttpClientConnectionManager connManagerCopy = this.connManager;
961         if (connManagerCopy == null) {
962             LayeredConnectionSocketFactory sslSocketFactoryCopy = this.sslSocketFactory;
963             if (sslSocketFactoryCopy == null) {
964                 final String[] supportedProtocols = systemProperties ? split(
965                         System.getProperty("https.protocols")) : null;
966                 final String[] supportedCipherSuites = systemProperties ? split(
967                         System.getProperty("https.cipherSuites")) : null;
968                 HostnameVerifier hostnameVerifierCopy = this.hostnameVerifier;
969                 if (hostnameVerifierCopy == null) {
970                     hostnameVerifierCopy = new DefaultHostnameVerifier(publicSuffixMatcherCopy);
971                 }
972                 if (sslContext != null) {
973                     sslSocketFactoryCopy = new SSLConnectionSocketFactory(
974                             sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifierCopy);
975                 } else {
976                     if (systemProperties) {
977                         sslSocketFactoryCopy = new SSLConnectionSocketFactory(
978                                 (SSLSocketFactory) SSLSocketFactory.getDefault(),
979                                 supportedProtocols, supportedCipherSuites, hostnameVerifierCopy);
980                     } else {
981                         sslSocketFactoryCopy = new SSLConnectionSocketFactory(
982                                 SSLContexts.createDefault(),
983                                 hostnameVerifierCopy);
984                     }
985                 }
986             }
987             @SuppressWarnings("resource")
988             final PoolingHttpClientConnectionManagerger.html#PoolingHttpClientConnectionManager">PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager(
989                     RegistryBuilder.<ConnectionSocketFactory>create()
990                         .register("http", PlainConnectionSocketFactory.getSocketFactory())
991                         .register("https", sslSocketFactoryCopy)
992                         .build(),
993                     null,
994                     null,
995                     dnsResolver,
996                     connTimeToLive,
997                     connTimeToLiveTimeUnit != null ? connTimeToLiveTimeUnit : TimeUnit.MILLISECONDS);
998             if (defaultSocketConfig != null) {
999                 poolingmgr.setDefaultSocketConfig(defaultSocketConfig);
1000             }
1001             if (defaultConnectionConfig != null) {
1002                 poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig);
1003             }
1004             if (systemProperties) {
1005                 String s = System.getProperty("http.keepAlive", "true");
1006                 if ("true".equalsIgnoreCase(s)) {
1007                     s = System.getProperty("http.maxConnections", "5");
1008                     final int max = Integer.parseInt(s);
1009                     poolingmgr.setDefaultMaxPerRoute(max);
1010                     poolingmgr.setMaxTotal(2 * max);
1011                 }
1012             }
1013             if (maxConnTotal > 0) {
1014                 poolingmgr.setMaxTotal(maxConnTotal);
1015             }
1016             if (maxConnPerRoute > 0) {
1017                 poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute);
1018             }
1019             connManagerCopy = poolingmgr;
1020         }
1021         ConnectionReuseStrategy reuseStrategyCopy = this.reuseStrategy;
1022         if (reuseStrategyCopy == null) {
1023             if (systemProperties) {
1024                 final String s = System.getProperty("http.keepAlive", "true");
1025                 if ("true".equalsIgnoreCase(s)) {
1026                     reuseStrategyCopy = DefaultClientConnectionReuseStrategy.INSTANCE;
1027                 } else {
1028                     reuseStrategyCopy = NoConnectionReuseStrategy.INSTANCE;
1029                 }
1030             } else {
1031                 reuseStrategyCopy = DefaultClientConnectionReuseStrategy.INSTANCE;
1032             }
1033         }
1034         ConnectionKeepAliveStrategy keepAliveStrategyCopy = this.keepAliveStrategy;
1035         if (keepAliveStrategyCopy == null) {
1036             keepAliveStrategyCopy = DefaultConnectionKeepAliveStrategy.INSTANCE;
1037         }
1038         AuthenticationStrategy targetAuthStrategyCopy = this.targetAuthStrategy;
1039         if (targetAuthStrategyCopy == null) {
1040             targetAuthStrategyCopy = TargetAuthenticationStrategy.INSTANCE;
1041         }
1042         AuthenticationStrategy proxyAuthStrategyCopy = this.proxyAuthStrategy;
1043         if (proxyAuthStrategyCopy == null) {
1044             proxyAuthStrategyCopy = ProxyAuthenticationStrategy.INSTANCE;
1045         }
1046         UserTokenHandler userTokenHandlerCopy = this.userTokenHandler;
1047         if (userTokenHandlerCopy == null) {
1048             if (!connectionStateDisabled) {
1049                 userTokenHandlerCopy = DefaultUserTokenHandler.INSTANCE;
1050             } else {
1051                 userTokenHandlerCopy = NoopUserTokenHandler.INSTANCE;
1052             }
1053         }
1054 
1055         String userAgentCopy = this.userAgent;
1056         if (userAgentCopy == null) {
1057             if (systemProperties) {
1058                 userAgentCopy = System.getProperty("http.agent");
1059             }
1060             if (userAgentCopy == null && !defaultUserAgentDisabled) {
1061                 userAgentCopy = VersionInfo.getUserAgent("Apache-HttpClient",
1062                         "org.apache.http.client", getClass());
1063             }
1064         }
1065 
1066         ClientExecChain execChain = createMainExec(
1067                 requestExecCopy,
1068                 connManagerCopy,
1069                 reuseStrategyCopy,
1070                 keepAliveStrategyCopy,
1071                 new ImmutableHttpProcessor(new RequestTargetHost(), new RequestUserAgent(userAgentCopy)),
1072                 targetAuthStrategyCopy,
1073                 proxyAuthStrategyCopy,
1074                 userTokenHandlerCopy);
1075 
1076         execChain = decorateMainExec(execChain);
1077 
1078         HttpProcessor httpprocessorCopy = this.httpprocessor;
1079         if (httpprocessorCopy == null) {
1080 
1081             final HttpProcessorBuilder b = HttpProcessorBuilder.create();
1082             if (requestFirst != null) {
1083                 for (final HttpRequestInterceptor i: requestFirst) {
1084                     b.addFirst(i);
1085                 }
1086             }
1087             if (responseFirst != null) {
1088                 for (final HttpResponseInterceptor i: responseFirst) {
1089                     b.addFirst(i);
1090                 }
1091             }
1092             b.addAll(
1093                     new RequestDefaultHeaders(defaultHeaders),
1094                     new RequestContent(),
1095                     new RequestTargetHost(),
1096                     new RequestClientConnControl(),
1097                     new RequestUserAgent(userAgentCopy),
1098                     new RequestExpectContinue());
1099             if (!cookieManagementDisabled) {
1100                 b.add(new RequestAddCookies());
1101             }
1102             if (!contentCompressionDisabled) {
1103                 if (contentDecoderMap != null) {
1104                     final List<String> encodings = new ArrayList<String>(contentDecoderMap.keySet());
1105                     Collections.sort(encodings);
1106                     b.add(new RequestAcceptEncoding(encodings));
1107                 } else {
1108                     b.add(new RequestAcceptEncoding());
1109                 }
1110             }
1111             if (!authCachingDisabled) {
1112                 b.add(new RequestAuthCache());
1113             }
1114             if (!cookieManagementDisabled) {
1115                 b.add(new ResponseProcessCookies());
1116             }
1117             if (!contentCompressionDisabled) {
1118                 if (contentDecoderMap != null) {
1119                     final RegistryBuilder<InputStreamFactory> b2 = RegistryBuilder.create();
1120                     for (final Map.Entry<String, InputStreamFactory> entry: contentDecoderMap.entrySet()) {
1121                         b2.register(entry.getKey(), entry.getValue());
1122                     }
1123                     b.add(new ResponseContentEncoding(b2.build()));
1124                 } else {
1125                     b.add(new ResponseContentEncoding());
1126                 }
1127             }
1128             if (requestLast != null) {
1129                 for (final HttpRequestInterceptor i: requestLast) {
1130                     b.addLast(i);
1131                 }
1132             }
1133             if (responseLast != null) {
1134                 for (final HttpResponseInterceptor i: responseLast) {
1135                     b.addLast(i);
1136                 }
1137             }
1138             httpprocessorCopy = b.build();
1139         }
1140         execChain = new ProtocolExec(execChain, httpprocessorCopy);
1141 
1142         execChain = decorateProtocolExec(execChain);
1143 
1144         // Add request retry executor, if not disabled
1145         if (!automaticRetriesDisabled) {
1146             HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;
1147             if (retryHandlerCopy == null) {
1148                 retryHandlerCopy = DefaultHttpRequestRetryHandler.INSTANCE;
1149             }
1150             execChain = new RetryExec(execChain, retryHandlerCopy);
1151         }
1152 
1153         HttpRoutePlanner routePlannerCopy = this.routePlanner;
1154         if (routePlannerCopy == null) {
1155             SchemePortResolver schemePortResolverCopy = this.schemePortResolver;
1156             if (schemePortResolverCopy == null) {
1157                 schemePortResolverCopy = DefaultSchemePortResolver.INSTANCE;
1158             }
1159             if (proxy != null) {
1160                 routePlannerCopy = new DefaultProxyRoutePlanner(proxy, schemePortResolverCopy);
1161             } else if (systemProperties) {
1162                 routePlannerCopy = new SystemDefaultRoutePlanner(
1163                         schemePortResolverCopy, ProxySelector.getDefault());
1164             } else {
1165                 routePlannerCopy = new DefaultRoutePlanner(schemePortResolverCopy);
1166             }
1167         }
1168 
1169         // Optionally, add service unavailable retry executor
1170         final ServiceUnavailableRetryStrategy serviceUnavailStrategyCopy = this.serviceUnavailStrategy;
1171         if (serviceUnavailStrategyCopy != null) {
1172             execChain = new ServiceUnavailableRetryExec(execChain, serviceUnavailStrategyCopy);
1173         }
1174 
1175         // Add redirect executor, if not disabled
1176         if (!redirectHandlingDisabled) {
1177             RedirectStrategy redirectStrategyCopy = this.redirectStrategy;
1178             if (redirectStrategyCopy == null) {
1179                 redirectStrategyCopy = DefaultRedirectStrategy.INSTANCE;
1180             }
1181             execChain = new RedirectExec(execChain, routePlannerCopy, redirectStrategyCopy);
1182         }
1183 
1184         // Optionally, add connection back-off executor
1185         if (this.backoffManager != null && this.connectionBackoffStrategy != null) {
1186             execChain = new BackoffStrategyExec(execChain, this.connectionBackoffStrategy, this.backoffManager);
1187         }
1188 
1189         Lookup<AuthSchemeProvider> authSchemeRegistryCopy = this.authSchemeRegistry;
1190         if (authSchemeRegistryCopy == null) {
1191             authSchemeRegistryCopy = RegistryBuilder.<AuthSchemeProvider>create()
1192                 .register(AuthSchemes.BASIC, new BasicSchemeFactory())
1193                 .register(AuthSchemes.DIGEST, new DigestSchemeFactory())
1194                 .register(AuthSchemes.NTLM, new NTLMSchemeFactory())
1195                 .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory())
1196                 .register(AuthSchemes.KERBEROS, new KerberosSchemeFactory())
1197                 .build();
1198         }
1199         Lookup<CookieSpecProvider> cookieSpecRegistryCopy = this.cookieSpecRegistry;
1200         if (cookieSpecRegistryCopy == null) {
1201             cookieSpecRegistryCopy = CookieSpecRegistries.createDefault(publicSuffixMatcherCopy);
1202         }
1203 
1204         CookieStore defaultCookieStore = this.cookieStore;
1205         if (defaultCookieStore == null) {
1206             defaultCookieStore = new BasicCookieStore();
1207         }
1208 
1209         CredentialsProvider defaultCredentialsProvider = this.credentialsProvider;
1210         if (defaultCredentialsProvider == null) {
1211             if (systemProperties) {
1212                 defaultCredentialsProvider = new SystemDefaultCredentialsProvider();
1213             } else {
1214                 defaultCredentialsProvider = new BasicCredentialsProvider();
1215             }
1216         }
1217 
1218         List<Closeable> closeablesCopy = closeables != null ? new ArrayList<Closeable>(closeables) : null;
1219         if (!this.connManagerShared) {
1220             if (closeablesCopy == null) {
1221                 closeablesCopy = new ArrayList<Closeable>(1);
1222             }
1223             final HttpClientConnectionManager cm = connManagerCopy;
1224 
1225             if (evictExpiredConnections || evictIdleConnections) {
1226                 final IdleConnectionEvictortml#IdleConnectionEvictor">IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor(cm,
1227                         maxIdleTime > 0 ? maxIdleTime : 10, maxIdleTimeUnit != null ? maxIdleTimeUnit : TimeUnit.SECONDS,
1228                         maxIdleTime, maxIdleTimeUnit);
1229                 closeablesCopy.add(new Closeable() {
1230 
1231                     @Override
1232                     public void close() throws IOException {
1233                         connectionEvictor.shutdown();
1234                         try {
1235                             connectionEvictor.awaitTermination(1L, TimeUnit.SECONDS);
1236                         } catch (final InterruptedException interrupted) {
1237                             Thread.currentThread().interrupt();
1238                         }
1239                     }
1240 
1241                 });
1242                 connectionEvictor.start();
1243             }
1244             closeablesCopy.add(new Closeable() {
1245 
1246                 @Override
1247                 public void close() throws IOException {
1248                     cm.shutdown();
1249                 }
1250 
1251             });
1252         }
1253 
1254         return new InternalHttpClient(
1255                 execChain,
1256                 connManagerCopy,
1257                 routePlannerCopy,
1258                 cookieSpecRegistryCopy,
1259                 authSchemeRegistryCopy,
1260                 defaultCookieStore,
1261                 defaultCredentialsProvider,
1262                 defaultRequestConfig != null ? defaultRequestConfig : RequestConfig.DEFAULT,
1263                 closeablesCopy);
1264     }
1265 
1266 }