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