/* * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.http.impl.client; import java.io.Closeable; import java.io.IOException; import java.net.ProxySelector; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import org.apache.http.ConnectionReuseStrategy; import org.apache.http.Header; import org.apache.http.HttpHost; import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpResponseInterceptor; import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AuthSchemeProvider; import org.apache.http.client.AuthenticationStrategy; import org.apache.http.client.BackoffManager; import org.apache.http.client.ConnectionBackoffStrategy; import org.apache.http.client.CookieStore; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.RedirectStrategy; import org.apache.http.client.ServiceUnavailableRetryStrategy; import org.apache.http.client.UserTokenHandler; import org.apache.http.client.config.AuthSchemes; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.InputStreamFactory; import org.apache.http.client.protocol.RequestAcceptEncoding; import org.apache.http.client.protocol.RequestAddCookies; import org.apache.http.client.protocol.RequestAuthCache; import org.apache.http.client.protocol.RequestClientConnControl; import org.apache.http.client.protocol.RequestDefaultHeaders; import org.apache.http.client.protocol.RequestExpectContinue; import org.apache.http.client.protocol.ResponseContentEncoding; import org.apache.http.client.protocol.ResponseProcessCookies; import org.apache.http.config.ConnectionConfig; import org.apache.http.config.Lookup; import org.apache.http.config.RegistryBuilder; import org.apache.http.config.SocketConfig; import org.apache.http.conn.ConnectionKeepAliveStrategy; import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.conn.SchemePortResolver; import org.apache.http.conn.routing.HttpRoutePlanner; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.LayeredConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.DefaultHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.conn.util.PublicSuffixMatcher; import org.apache.http.conn.util.PublicSuffixMatcherLoader; import org.apache.http.cookie.CookieSpecProvider; import org.apache.http.impl.DefaultConnectionReuseStrategy; import org.apache.http.impl.NoConnectionReuseStrategy; import org.apache.http.impl.auth.BasicSchemeFactory; import org.apache.http.impl.auth.DigestSchemeFactory; import org.apache.http.impl.auth.KerberosSchemeFactory; import org.apache.http.impl.auth.NTLMSchemeFactory; import org.apache.http.impl.auth.SPNegoSchemeFactory; import org.apache.http.impl.conn.DefaultProxyRoutePlanner; import org.apache.http.impl.conn.DefaultRoutePlanner; import org.apache.http.impl.conn.DefaultSchemePortResolver; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.impl.conn.SystemDefaultRoutePlanner; import org.apache.http.impl.execchain.BackoffStrategyExec; import org.apache.http.impl.execchain.ClientExecChain; import org.apache.http.impl.execchain.MainClientExec; import org.apache.http.impl.execchain.ProtocolExec; import org.apache.http.impl.execchain.RedirectExec; import org.apache.http.impl.execchain.RetryExec; import org.apache.http.impl.execchain.ServiceUnavailableRetryExec; import org.apache.http.protocol.HttpProcessor; import org.apache.http.protocol.HttpProcessorBuilder; import org.apache.http.protocol.HttpRequestExecutor; import org.apache.http.protocol.ImmutableHttpProcessor; import org.apache.http.protocol.RequestContent; import org.apache.http.protocol.RequestTargetHost; import org.apache.http.protocol.RequestUserAgent; import org.apache.http.ssl.SSLContexts; import org.apache.http.util.TextUtils; import org.apache.http.util.VersionInfo; /** * Builder for {@link CloseableHttpClient} instances. * <p> * When a particular component is not explicitly set this class will * use its default implementation. System properties will be taken * into account when configuring the default implementations when * {@link #useSystemProperties()} method is called prior to calling * {@link #build()}. * </p> * <ul> * <li>ssl.TrustManagerFactory.algorithm</li> * <li>javax.net.ssl.trustStoreType</li> * <li>javax.net.ssl.trustStore</li> * <li>javax.net.ssl.trustStoreProvider</li> * <li>javax.net.ssl.trustStorePassword</li> * <li>ssl.KeyManagerFactory.algorithm</li> * <li>javax.net.ssl.keyStoreType</li> * <li>javax.net.ssl.keyStore</li> * <li>javax.net.ssl.keyStoreProvider</li> * <li>javax.net.ssl.keyStorePassword</li> * <li>https.protocols</li> * <li>https.cipherSuites</li> * <li>http.proxyHost</li> * <li>http.proxyPort</li> * <li>http.nonProxyHosts</li> * <li>http.keepAlive</li> * <li>http.maxConnections</li> * <li>http.agent</li> * </ul> * <p> * Please note that some settings used by this class can be mutually * exclusive and may not apply when building {@link CloseableHttpClient} * instances. * </p> * * @since 4.3 */ @NotThreadSafe public class HttpClientBuilder { private HttpRequestExecutor requestExec; private HostnameVerifier hostnameVerifier; private LayeredConnectionSocketFactory sslSocketFactory; private SSLContext sslContext; private HttpClientConnectionManager connManager; private boolean connManagerShared; private SchemePortResolver schemePortResolver; private ConnectionReuseStrategy reuseStrategy; private ConnectionKeepAliveStrategy keepAliveStrategy; private AuthenticationStrategy targetAuthStrategy; private AuthenticationStrategy proxyAuthStrategy; private UserTokenHandler userTokenHandler; private HttpProcessor httpprocessor; private LinkedList<HttpRequestInterceptor> requestFirst; private LinkedList<HttpRequestInterceptor> requestLast; private LinkedList<HttpResponseInterceptor> responseFirst; private LinkedList<HttpResponseInterceptor> responseLast; private HttpRequestRetryHandler retryHandler; private HttpRoutePlanner routePlanner; private RedirectStrategy redirectStrategy; private ConnectionBackoffStrategy connectionBackoffStrategy; private BackoffManager backoffManager; private ServiceUnavailableRetryStrategy serviceUnavailStrategy; private Lookup<AuthSchemeProvider> authSchemeRegistry; private Lookup<CookieSpecProvider> cookieSpecRegistry; private Map<String, InputStreamFactory> contentDecoderMap; private CookieStore cookieStore; private CredentialsProvider credentialsProvider; private String userAgent; private HttpHost proxy; private Collection<? extends Header> defaultHeaders; private SocketConfig defaultSocketConfig; private ConnectionConfig defaultConnectionConfig; private RequestConfig defaultRequestConfig; private boolean evictExpiredConnections; private boolean evictIdleConnections; private long maxIdleTime; private TimeUnit maxIdleTimeUnit; private boolean systemProperties; private boolean redirectHandlingDisabled; private boolean automaticRetriesDisabled; private boolean contentCompressionDisabled; private boolean cookieManagementDisabled; private boolean authCachingDisabled; private boolean connectionStateDisabled; private int maxConnTotal = 0; private int maxConnPerRoute = 0; private long connTimeToLive = -1; private TimeUnit connTimeToLiveTimeUnit = TimeUnit.MILLISECONDS; private List<Closeable> closeables; private PublicSuffixMatcher publicSuffixMatcher; public static HttpClientBuilder create() { return new HttpClientBuilder(); } protected HttpClientBuilder() { super(); } /** * Assigns {@link HttpRequestExecutor} instance. */ public final HttpClientBuilder setRequestExecutor(final HttpRequestExecutor requestExec) { this.requestExec = requestExec; return this; } /** * Assigns {@link X509HostnameVerifier} instance. * <p> * Please note this value can be overridden by the {@link #setConnectionManager( * org.apache.http.conn.HttpClientConnectionManager)} and the {@link #setSSLSocketFactory( * org.apache.http.conn.socket.LayeredConnectionSocketFactory)} methods. * </p> * * @deprecated (4.4) */ @Deprecated public final HttpClientBuilder setHostnameVerifier(final X509HostnameVerifier hostnameVerifier) { this.hostnameVerifier = hostnameVerifier; return this; } /** * Assigns {@link javax.net.ssl.HostnameVerifier} instance. * <p> * Please note this value can be overridden by the {@link #setConnectionManager( * org.apache.http.conn.HttpClientConnectionManager)} and the {@link #setSSLSocketFactory( * org.apache.http.conn.socket.LayeredConnectionSocketFactory)} methods. * </p> * * @since 4.4 */ public final HttpClientBuilder setSSLHostnameVerifier(final HostnameVerifier hostnameVerifier) { this.hostnameVerifier = hostnameVerifier; return this; } /** * Assigns file containing public suffix matcher. Instances of this class can be created * with {@link org.apache.http.conn.util.PublicSuffixMatcherLoader}. * * @see org.apache.http.conn.util.PublicSuffixMatcher * @see org.apache.http.conn.util.PublicSuffixMatcherLoader * * @since 4.4 */ public final HttpClientBuilder setPublicSuffixMatcher(final PublicSuffixMatcher publicSuffixMatcher) { this.publicSuffixMatcher = publicSuffixMatcher; return this; } /** * Assigns {@link SSLContext} instance. * <p> * Please note this value can be overridden by the {@link #setConnectionManager( * org.apache.http.conn.HttpClientConnectionManager)} and the {@link #setSSLSocketFactory( * org.apache.http.conn.socket.LayeredConnectionSocketFactory)} methods. * </p> * * @deprecated (4.5) use {@link #setSSLContext(SSLContext)} */ @Deprecated public final HttpClientBuilder setSslcontext(final SSLContext sslcontext) { return setSSLContext(sslcontext); } /** * Assigns {@link SSLContext} instance. * <p> * Please note this value can be overridden by the {@link #setConnectionManager( * org.apache.http.conn.HttpClientConnectionManager)} and the {@link #setSSLSocketFactory( * org.apache.http.conn.socket.LayeredConnectionSocketFactory)} methods. * </p> */ public final HttpClientBuilder setSSLContext(final SSLContext sslContext) { this.sslContext = sslContext; return this; } /** * Assigns {@link LayeredConnectionSocketFactory} instance. * <p> * Please note this value can be overridden by the {@link #setConnectionManager( * org.apache.http.conn.HttpClientConnectionManager)} method. * </p> */ public final HttpClientBuilder setSSLSocketFactory( final LayeredConnectionSocketFactory sslSocketFactory) { this.sslSocketFactory = sslSocketFactory; return this; } /** * Assigns maximum total connection value. * <p> * Please note this value can be overridden by the {@link #setConnectionManager( * org.apache.http.conn.HttpClientConnectionManager)} method. * </p> */ public final HttpClientBuilder setMaxConnTotal(final int maxConnTotal) { this.maxConnTotal = maxConnTotal; return this; } /** * Assigns maximum connection per route value. * <p> * Please note this value can be overridden by the {@link #setConnectionManager( * org.apache.http.conn.HttpClientConnectionManager)} method. * </p> */ public final HttpClientBuilder setMaxConnPerRoute(final int maxConnPerRoute) { this.maxConnPerRoute = maxConnPerRoute; return this; } /** * Assigns default {@link SocketConfig}. * <p> * Please note this value can be overridden by the {@link #setConnectionManager( * org.apache.http.conn.HttpClientConnectionManager)} method. * </p> */ public final HttpClientBuilder setDefaultSocketConfig(final SocketConfig config) { this.defaultSocketConfig = config; return this; } /** * Assigns default {@link ConnectionConfig}. * <p> * Please note this value can be overridden by the {@link #setConnectionManager( * org.apache.http.conn.HttpClientConnectionManager)} method. * </p> */ public final HttpClientBuilder setDefaultConnectionConfig(final ConnectionConfig config) { this.defaultConnectionConfig = config; return this; } /** * Sets maximum time to live for persistent connections * <p> * Please note this value can be overridden by the {@link #setConnectionManager( * org.apache.http.conn.HttpClientConnectionManager)} method. * </p> * * @since 4.4 */ public final HttpClientBuilder setConnectionTimeToLive(final long connTimeToLive, final TimeUnit connTimeToLiveTimeUnit) { this.connTimeToLive = connTimeToLive; this.connTimeToLiveTimeUnit = connTimeToLiveTimeUnit; return this; } /** * Assigns {@link HttpClientConnectionManager} instance. */ public final HttpClientBuilder setConnectionManager( final HttpClientConnectionManager connManager) { this.connManager = connManager; return this; } /** * Defines the connection manager is to be shared by multiple * client instances. * <p> * If the connection manager is shared its life-cycle is expected * to be managed by the caller and it will not be shut down * if the client is closed. * </p> * * @param shared defines whether or not the connection manager can be shared * by multiple clients. * * @since 4.4 */ public final HttpClientBuilder setConnectionManagerShared( final boolean shared) { this.connManagerShared = shared; return this; } /** * Assigns {@link ConnectionReuseStrategy} instance. */ public final HttpClientBuilder setConnectionReuseStrategy( final ConnectionReuseStrategy reuseStrategy) { this.reuseStrategy = reuseStrategy; return this; } /** * Assigns {@link ConnectionKeepAliveStrategy} instance. */ public final HttpClientBuilder setKeepAliveStrategy( final ConnectionKeepAliveStrategy keepAliveStrategy) { this.keepAliveStrategy = keepAliveStrategy; return this; } /** * Assigns {@link AuthenticationStrategy} instance for target * host authentication. */ public final HttpClientBuilder setTargetAuthenticationStrategy( final AuthenticationStrategy targetAuthStrategy) { this.targetAuthStrategy = targetAuthStrategy; return this; } /** * Assigns {@link AuthenticationStrategy} instance for proxy * authentication. */ public final HttpClientBuilder setProxyAuthenticationStrategy( final AuthenticationStrategy proxyAuthStrategy) { this.proxyAuthStrategy = proxyAuthStrategy; return this; } /** * Assigns {@link UserTokenHandler} instance. * <p> * Please note this value can be overridden by the {@link #disableConnectionState()} * method. * </p> */ public final HttpClientBuilder setUserTokenHandler(final UserTokenHandler userTokenHandler) { this.userTokenHandler = userTokenHandler; return this; } /** * Disables connection state tracking. */ public final HttpClientBuilder disableConnectionState() { connectionStateDisabled = true; return this; } /** * Assigns {@link SchemePortResolver} instance. */ public final HttpClientBuilder setSchemePortResolver( final SchemePortResolver schemePortResolver) { this.schemePortResolver = schemePortResolver; return this; } /** * Assigns {@code User-Agent} value. * <p> * Please note this value can be overridden by the {@link #setHttpProcessor( * org.apache.http.protocol.HttpProcessor)} method. * </p> */ public final HttpClientBuilder setUserAgent(final String userAgent) { this.userAgent = userAgent; return this; } /** * Assigns default request header values. * <p> * Please note this value can be overridden by the {@link #setHttpProcessor( * org.apache.http.protocol.HttpProcessor)} method. * </p> */ public final HttpClientBuilder setDefaultHeaders(final Collection<? extends Header> defaultHeaders) { this.defaultHeaders = defaultHeaders; return this; } /** * Adds this protocol interceptor to the head of the protocol processing list. * <p> * Please note this value can be overridden by the {@link #setHttpProcessor( * org.apache.http.protocol.HttpProcessor)} method. * </p> */ public final HttpClientBuilder addInterceptorFirst(final HttpResponseInterceptor itcp) { if (itcp == null) { return this; } if (responseFirst == null) { responseFirst = new LinkedList<HttpResponseInterceptor>(); } responseFirst.addFirst(itcp); return this; } /** * Adds this protocol interceptor to the tail of the protocol processing list. * <p> * Please note this value can be overridden by the {@link #setHttpProcessor( * org.apache.http.protocol.HttpProcessor)} method. * </p> */ public final HttpClientBuilder addInterceptorLast(final HttpResponseInterceptor itcp) { if (itcp == null) { return this; } if (responseLast == null) { responseLast = new LinkedList<HttpResponseInterceptor>(); } responseLast.addLast(itcp); return this; } /** * Adds this protocol interceptor to the head of the protocol processing list. * <p> * Please note this value can be overridden by the {@link #setHttpProcessor( * org.apache.http.protocol.HttpProcessor)} method. */ public final HttpClientBuilder addInterceptorFirst(final HttpRequestInterceptor itcp) { if (itcp == null) { return this; } if (requestFirst == null) { requestFirst = new LinkedList<HttpRequestInterceptor>(); } requestFirst.addFirst(itcp); return this; } /** * Adds this protocol interceptor to the tail of the protocol processing list. * <p> * Please note this value can be overridden by the {@link #setHttpProcessor( * org.apache.http.protocol.HttpProcessor)} method. */ public final HttpClientBuilder addInterceptorLast(final HttpRequestInterceptor itcp) { if (itcp == null) { return this; } if (requestLast == null) { requestLast = new LinkedList<HttpRequestInterceptor>(); } requestLast.addLast(itcp); return this; } /** * Disables state (cookie) management. * <p> * Please note this value can be overridden by the {@link #setHttpProcessor( * org.apache.http.protocol.HttpProcessor)} method. */ public final HttpClientBuilder disableCookieManagement() { this.cookieManagementDisabled = true; return this; } /** * Disables automatic content decompression. * <p> * Please note this value can be overridden by the {@link #setHttpProcessor( * org.apache.http.protocol.HttpProcessor)} method. */ public final HttpClientBuilder disableContentCompression() { contentCompressionDisabled = true; return this; } /** * Disables authentication scheme caching. * <p> * Please note this value can be overridden by the {@link #setHttpProcessor( * org.apache.http.protocol.HttpProcessor)} method. */ public final HttpClientBuilder disableAuthCaching() { this.authCachingDisabled = true; return this; } /** * Assigns {@link HttpProcessor} instance. */ public final HttpClientBuilder setHttpProcessor(final HttpProcessor httpprocessor) { this.httpprocessor = httpprocessor; return this; } /** * Assigns {@link HttpRequestRetryHandler} instance. * <p> * Please note this value can be overridden by the {@link #disableAutomaticRetries()} * method. */ public final HttpClientBuilder setRetryHandler(final HttpRequestRetryHandler retryHandler) { this.retryHandler = retryHandler; return this; } /** * Disables automatic request recovery and re-execution. */ public final HttpClientBuilder disableAutomaticRetries() { automaticRetriesDisabled = true; return this; } /** * Assigns default proxy value. * <p> * Please note this value can be overridden by the {@link #setRoutePlanner( * org.apache.http.conn.routing.HttpRoutePlanner)} method. */ public final HttpClientBuilder setProxy(final HttpHost proxy) { this.proxy = proxy; return this; } /** * Assigns {@link HttpRoutePlanner} instance. */ public final HttpClientBuilder setRoutePlanner(final HttpRoutePlanner routePlanner) { this.routePlanner = routePlanner; return this; } /** * Assigns {@link RedirectStrategy} instance. * <p> * Please note this value can be overridden by the {@link #disableRedirectHandling()} * method. * </p> ` */ public final HttpClientBuilder setRedirectStrategy(final RedirectStrategy redirectStrategy) { this.redirectStrategy = redirectStrategy; return this; } /** * Disables automatic redirect handling. */ public final HttpClientBuilder disableRedirectHandling() { redirectHandlingDisabled = true; return this; } /** * Assigns {@link ConnectionBackoffStrategy} instance. */ public final HttpClientBuilder setConnectionBackoffStrategy( final ConnectionBackoffStrategy connectionBackoffStrategy) { this.connectionBackoffStrategy = connectionBackoffStrategy; return this; } /** * Assigns {@link BackoffManager} instance. */ public final HttpClientBuilder setBackoffManager(final BackoffManager backoffManager) { this.backoffManager = backoffManager; return this; } /** * Assigns {@link ServiceUnavailableRetryStrategy} instance. */ public final HttpClientBuilder setServiceUnavailableRetryStrategy( final ServiceUnavailableRetryStrategy serviceUnavailStrategy) { this.serviceUnavailStrategy = serviceUnavailStrategy; return this; } /** * Assigns default {@link CookieStore} instance which will be used for * request execution if not explicitly set in the client execution context. */ public final HttpClientBuilder setDefaultCookieStore(final CookieStore cookieStore) { this.cookieStore = cookieStore; return this; } /** * Assigns default {@link CredentialsProvider} instance which will be used * for request execution if not explicitly set in the client execution * context. */ public final HttpClientBuilder setDefaultCredentialsProvider( final CredentialsProvider credentialsProvider) { this.credentialsProvider = credentialsProvider; return this; } /** * Assigns default {@link org.apache.http.auth.AuthScheme} registry which will * be used for request execution if not explicitly set in the client execution * context. */ public final HttpClientBuilder setDefaultAuthSchemeRegistry( final Lookup<AuthSchemeProvider> authSchemeRegistry) { this.authSchemeRegistry = authSchemeRegistry; return this; } /** * Assigns default {@link org.apache.http.cookie.CookieSpec} registry which will * be used for request execution if not explicitly set in the client execution * context. * * @see org.apache.http.impl.client.CookieSpecRegistries * */ public final HttpClientBuilder setDefaultCookieSpecRegistry( final Lookup<CookieSpecProvider> cookieSpecRegistry) { this.cookieSpecRegistry = cookieSpecRegistry; return this; } /** * Assigns a map of {@link org.apache.http.client.entity.InputStreamFactory}s * to be used for automatic content decompression. */ public final HttpClientBuilder setContentDecoderRegistry( final Map<String, InputStreamFactory> contentDecoderMap) { this.contentDecoderMap = contentDecoderMap; return this; } /** * Assigns default {@link RequestConfig} instance which will be used * for request execution if not explicitly set in the client execution * context. */ public final HttpClientBuilder setDefaultRequestConfig(final RequestConfig config) { this.defaultRequestConfig = config; return this; } /** * Use system properties when creating and configuring default * implementations. */ public final HttpClientBuilder useSystemProperties() { this.systemProperties = true; return this; } /** * Makes this instance of HttpClient proactively evict expired connections from the * connection pool using a background thread. * <p> * One MUST explicitly close HttpClient with {@link CloseableHttpClient#close()} in order * to stop and release the background thread. * <p> * Please note this method has no effect if the instance of HttpClient is configuted to * use a shared connection manager. * <p> * Please note this method may not be used when the instance of HttpClient is created * inside an EJB container. * * @see #setConnectionManagerShared(boolean) * @see org.apache.http.conn.HttpClientConnectionManager#closeExpiredConnections() * * @since 4.4 */ public final HttpClientBuilder evictExpiredConnections() { evictExpiredConnections = true; return this; } /** * Makes this instance of HttpClient proactively evict idle connections from the * connection pool using a background thread. * <p> * One MUST explicitly close HttpClient with {@link CloseableHttpClient#close()} in order * to stop and release the background thread. * <p> * Please note this method has no effect if the instance of HttpClient is configuted to * use a shared connection manager. * <p> * Please note this method may not be used when the instance of HttpClient is created * inside an EJB container. * * @see #setConnectionManagerShared(boolean) * @see org.apache.http.conn.HttpClientConnectionManager#closeExpiredConnections() * * @param maxIdleTime maximum time persistent connections can stay idle while kept alive * in the connection pool. Connections whose inactivity period exceeds this value will * get closed and evicted from the pool. * @param maxIdleTimeUnit time unit for the above parameter. * * @deprecated (4.5) use {@link #evictIdleConnections(long, TimeUnit)} * * @since 4.4 */ @Deprecated public final HttpClientBuilder evictIdleConnections(final Long maxIdleTime, final TimeUnit maxIdleTimeUnit) { return evictIdleConnections(maxIdleTime.longValue(), maxIdleTimeUnit); } /** * Makes this instance of HttpClient proactively evict idle connections from the * connection pool using a background thread. * <p> * One MUST explicitly close HttpClient with {@link CloseableHttpClient#close()} in order * to stop and release the background thread. * <p> * Please note this method has no effect if the instance of HttpClient is configuted to * use a shared connection manager. * <p> * Please note this method may not be used when the instance of HttpClient is created * inside an EJB container. * * @see #setConnectionManagerShared(boolean) * @see org.apache.http.conn.HttpClientConnectionManager#closeExpiredConnections() * * @param maxIdleTime maximum time persistent connections can stay idle while kept alive * in the connection pool. Connections whose inactivity period exceeds this value will * get closed and evicted from the pool. * @param maxIdleTimeUnit time unit for the above parameter. * * @since 4.4 */ public final HttpClientBuilder evictIdleConnections(final long maxIdleTime, final TimeUnit maxIdleTimeUnit) { this.evictIdleConnections = true; this.maxIdleTime = maxIdleTime; this.maxIdleTimeUnit = maxIdleTimeUnit; return this; } /** * Produces an instance of {@link ClientExecChain} to be used as a main exec. * <p> * Default implementation produces an instance of {@link MainClientExec} * </p> * <p> * For internal use. * </p> * * @since 4.4 */ protected ClientExecChain createMainExec( final HttpRequestExecutor requestExec, final HttpClientConnectionManager connManager, final ConnectionReuseStrategy reuseStrategy, final ConnectionKeepAliveStrategy keepAliveStrategy, final HttpProcessor proxyHttpProcessor, final AuthenticationStrategy targetAuthStrategy, final AuthenticationStrategy proxyAuthStrategy, final UserTokenHandler userTokenHandler) { return new MainClientExec( requestExec, connManager, reuseStrategy, keepAliveStrategy, proxyHttpProcessor, targetAuthStrategy, proxyAuthStrategy, userTokenHandler); } /** * For internal use. */ protected ClientExecChain decorateMainExec(final ClientExecChain mainExec) { return mainExec; } /** * For internal use. */ protected ClientExecChain decorateProtocolExec(final ClientExecChain protocolExec) { return protocolExec; } /** * For internal use. */ protected void addCloseable(final Closeable closeable) { if (closeable == null) { return; } if (closeables == null) { closeables = new ArrayList<Closeable>(); } closeables.add(closeable); } private static String[] split(final String s) { if (TextUtils.isBlank(s)) { return null; } return s.split(" *, *"); } public CloseableHttpClient build() { // Create main request executor // We copy the instance fields to avoid changing them, and rename to avoid accidental use of the wrong version PublicSuffixMatcher publicSuffixMatcherCopy = this.publicSuffixMatcher; if (publicSuffixMatcherCopy == null) { publicSuffixMatcherCopy = PublicSuffixMatcherLoader.getDefault(); } HttpRequestExecutor requestExecCopy = this.requestExec; if (requestExecCopy == null) { requestExecCopy = new HttpRequestExecutor(); } HttpClientConnectionManager connManagerCopy = this.connManager; if (connManagerCopy == null) { LayeredConnectionSocketFactory sslSocketFactoryCopy = this.sslSocketFactory; if (sslSocketFactoryCopy == null) { final String[] supportedProtocols = systemProperties ? split( System.getProperty("https.protocols")) : null; final String[] supportedCipherSuites = systemProperties ? split( System.getProperty("https.cipherSuites")) : null; HostnameVerifier hostnameVerifierCopy = this.hostnameVerifier; if (hostnameVerifierCopy == null) { hostnameVerifierCopy = new DefaultHostnameVerifier(publicSuffixMatcherCopy); } if (sslContext != null) { sslSocketFactoryCopy = new SSLConnectionSocketFactory( sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifierCopy); } else { if (systemProperties) { sslSocketFactoryCopy = new SSLConnectionSocketFactory( (SSLSocketFactory) SSLSocketFactory.getDefault(), supportedProtocols, supportedCipherSuites, hostnameVerifierCopy); } else { sslSocketFactoryCopy = new SSLConnectionSocketFactory( SSLContexts.createDefault(), hostnameVerifierCopy); } } } @SuppressWarnings("resource") final PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager( RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", sslSocketFactoryCopy) .build(), null, null, null, connTimeToLive, connTimeToLiveTimeUnit != null ? connTimeToLiveTimeUnit : TimeUnit.MILLISECONDS); if (defaultSocketConfig != null) { poolingmgr.setDefaultSocketConfig(defaultSocketConfig); } if (defaultConnectionConfig != null) { poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig); } if (systemProperties) { String s = System.getProperty("http.keepAlive", "true"); if ("true".equalsIgnoreCase(s)) { s = System.getProperty("http.maxConnections", "5"); final int max = Integer.parseInt(s); poolingmgr.setDefaultMaxPerRoute(max); poolingmgr.setMaxTotal(2 * max); } } if (maxConnTotal > 0) { poolingmgr.setMaxTotal(maxConnTotal); } if (maxConnPerRoute > 0) { poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute); } connManagerCopy = poolingmgr; } ConnectionReuseStrategy reuseStrategyCopy = this.reuseStrategy; if (reuseStrategyCopy == null) { if (systemProperties) { final String s = System.getProperty("http.keepAlive", "true"); if ("true".equalsIgnoreCase(s)) { reuseStrategyCopy = DefaultConnectionReuseStrategy.INSTANCE; } else { reuseStrategyCopy = NoConnectionReuseStrategy.INSTANCE; } } else { reuseStrategyCopy = DefaultConnectionReuseStrategy.INSTANCE; } } ConnectionKeepAliveStrategy keepAliveStrategyCopy = this.keepAliveStrategy; if (keepAliveStrategyCopy == null) { keepAliveStrategyCopy = DefaultConnectionKeepAliveStrategy.INSTANCE; } AuthenticationStrategy targetAuthStrategyCopy = this.targetAuthStrategy; if (targetAuthStrategyCopy == null) { targetAuthStrategyCopy = TargetAuthenticationStrategy.INSTANCE; } AuthenticationStrategy proxyAuthStrategyCopy = this.proxyAuthStrategy; if (proxyAuthStrategyCopy == null) { proxyAuthStrategyCopy = ProxyAuthenticationStrategy.INSTANCE; } UserTokenHandler userTokenHandlerCopy = this.userTokenHandler; if (userTokenHandlerCopy == null) { if (!connectionStateDisabled) { userTokenHandlerCopy = DefaultUserTokenHandler.INSTANCE; } else { userTokenHandlerCopy = NoopUserTokenHandler.INSTANCE; } } String userAgentCopy = this.userAgent; if (userAgentCopy == null) { if (systemProperties) { userAgentCopy = System.getProperty("http.agent"); } if (userAgentCopy == null) { userAgentCopy = VersionInfo.getUserAgent("Apache-HttpClient", "org.apache.http.client", getClass()); } } ClientExecChain execChain = createMainExec( requestExecCopy, connManagerCopy, reuseStrategyCopy, keepAliveStrategyCopy, new ImmutableHttpProcessor(new RequestTargetHost(), new RequestUserAgent(userAgentCopy)), targetAuthStrategyCopy, proxyAuthStrategyCopy, userTokenHandlerCopy); execChain = decorateMainExec(execChain); HttpProcessor httpprocessorCopy = this.httpprocessor; if (httpprocessorCopy == null) { final HttpProcessorBuilder b = HttpProcessorBuilder.create(); if (requestFirst != null) { for (final HttpRequestInterceptor i: requestFirst) { b.addFirst(i); } } if (responseFirst != null) { for (final HttpResponseInterceptor i: responseFirst) { b.addFirst(i); } } b.addAll( new RequestDefaultHeaders(defaultHeaders), new RequestContent(), new RequestTargetHost(), new RequestClientConnControl(), new RequestUserAgent(userAgentCopy), new RequestExpectContinue()); if (!cookieManagementDisabled) { b.add(new RequestAddCookies()); } if (!contentCompressionDisabled) { if (contentDecoderMap != null) { final List<String> encodings = new ArrayList<String>(contentDecoderMap.keySet()); Collections.sort(encodings); b.add(new RequestAcceptEncoding(encodings)); } else { b.add(new RequestAcceptEncoding()); } } if (!authCachingDisabled) { b.add(new RequestAuthCache()); } if (!cookieManagementDisabled) { b.add(new ResponseProcessCookies()); } if (!contentCompressionDisabled) { if (contentDecoderMap != null) { final RegistryBuilder<InputStreamFactory> b2 = RegistryBuilder.create(); for (Map.Entry<String, InputStreamFactory> entry: contentDecoderMap.entrySet()) { b2.register(entry.getKey(), entry.getValue()); } b.add(new ResponseContentEncoding(b2.build())); } else { b.add(new ResponseContentEncoding()); } } if (requestLast != null) { for (final HttpRequestInterceptor i: requestLast) { b.addLast(i); } } if (responseLast != null) { for (final HttpResponseInterceptor i: responseLast) { b.addLast(i); } } httpprocessorCopy = b.build(); } execChain = new ProtocolExec(execChain, httpprocessorCopy); execChain = decorateProtocolExec(execChain); // Add request retry executor, if not disabled if (!automaticRetriesDisabled) { HttpRequestRetryHandler retryHandlerCopy = this.retryHandler; if (retryHandlerCopy == null) { retryHandlerCopy = DefaultHttpRequestRetryHandler.INSTANCE; } execChain = new RetryExec(execChain, retryHandlerCopy); } HttpRoutePlanner routePlannerCopy = this.routePlanner; if (routePlannerCopy == null) { SchemePortResolver schemePortResolverCopy = this.schemePortResolver; if (schemePortResolverCopy == null) { schemePortResolverCopy = DefaultSchemePortResolver.INSTANCE; } if (proxy != null) { routePlannerCopy = new DefaultProxyRoutePlanner(proxy, schemePortResolverCopy); } else if (systemProperties) { routePlannerCopy = new SystemDefaultRoutePlanner( schemePortResolverCopy, ProxySelector.getDefault()); } else { routePlannerCopy = new DefaultRoutePlanner(schemePortResolverCopy); } } // Add redirect executor, if not disabled if (!redirectHandlingDisabled) { RedirectStrategy redirectStrategyCopy = this.redirectStrategy; if (redirectStrategyCopy == null) { redirectStrategyCopy = DefaultRedirectStrategy.INSTANCE; } execChain = new RedirectExec(execChain, routePlannerCopy, redirectStrategyCopy); } // Optionally, add service unavailable retry executor final ServiceUnavailableRetryStrategy serviceUnavailStrategyCopy = this.serviceUnavailStrategy; if (serviceUnavailStrategyCopy != null) { execChain = new ServiceUnavailableRetryExec(execChain, serviceUnavailStrategyCopy); } // Optionally, add connection back-off executor if (this.backoffManager != null && this.connectionBackoffStrategy != null) { execChain = new BackoffStrategyExec(execChain, this.connectionBackoffStrategy, this.backoffManager); } Lookup<AuthSchemeProvider> authSchemeRegistryCopy = this.authSchemeRegistry; if (authSchemeRegistryCopy == null) { authSchemeRegistryCopy = RegistryBuilder.<AuthSchemeProvider>create() .register(AuthSchemes.BASIC, new BasicSchemeFactory()) .register(AuthSchemes.DIGEST, new DigestSchemeFactory()) .register(AuthSchemes.NTLM, new NTLMSchemeFactory()) .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory()) .register(AuthSchemes.KERBEROS, new KerberosSchemeFactory()) .build(); } Lookup<CookieSpecProvider> cookieSpecRegistryCopy = this.cookieSpecRegistry; if (cookieSpecRegistryCopy == null) { cookieSpecRegistryCopy = CookieSpecRegistries.createDefault(publicSuffixMatcherCopy); } CookieStore defaultCookieStore = this.cookieStore; if (defaultCookieStore == null) { defaultCookieStore = new BasicCookieStore(); } CredentialsProvider defaultCredentialsProvider = this.credentialsProvider; if (defaultCredentialsProvider == null) { if (systemProperties) { defaultCredentialsProvider = new SystemDefaultCredentialsProvider(); } else { defaultCredentialsProvider = new BasicCredentialsProvider(); } } List<Closeable> closeablesCopy = closeables != null ? new ArrayList<Closeable>(closeables) : null; if (!this.connManagerShared) { if (closeablesCopy == null) { closeablesCopy = new ArrayList<Closeable>(1); } final HttpClientConnectionManager cm = connManagerCopy; if (evictExpiredConnections || evictIdleConnections) { final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor(cm, maxIdleTime > 0 ? maxIdleTime : 10, maxIdleTimeUnit != null ? maxIdleTimeUnit : TimeUnit.SECONDS); closeablesCopy.add(new Closeable() { @Override public void close() throws IOException { connectionEvictor.shutdown(); } }); connectionEvictor.start(); } closeablesCopy.add(new Closeable() { @Override public void close() throws IOException { cm.shutdown(); } }); } return new InternalHttpClient( execChain, connManagerCopy, routePlannerCopy, cookieSpecRegistryCopy, authSchemeRegistryCopy, defaultCookieStore, defaultCredentialsProvider, defaultRequestConfig != null ? defaultRequestConfig : RequestConfig.DEFAULT, closeablesCopy); } }
/* * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.http.impl.client; import org.apache.http.HeaderElement; import org.apache.http.HeaderElementIterator; import org.apache.http.HttpResponse; import org.apache.http.annotation.Immutable; import org.apache.http.conn.ConnectionKeepAliveStrategy; import org.apache.http.message.BasicHeaderElementIterator; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.apache.http.util.Args; /** * Default implementation of a strategy deciding duration * that a connection can remain idle. * * The default implementation looks solely at the 'Keep-Alive' * header's timeout token. * * @since 4.0 */ @Immutable public class DefaultConnectionKeepAliveStrategy implements ConnectionKeepAliveStrategy { public static final DefaultConnectionKeepAliveStrategy INSTANCE = new DefaultConnectionKeepAliveStrategy(); @Override public long getKeepAliveDuration(final HttpResponse response, final HttpContext context) { Args.notNull(response, "HTTP response"); final HeaderElementIterator it = new BasicHeaderElementIterator( response.headerIterator(HTTP.CONN_KEEP_ALIVE)); while (it.hasNext()) { final HeaderElement he = it.nextElement(); final String param = he.getName(); final String value = he.getValue(); if (value != null && param.equalsIgnoreCase("timeout")) { try { return Long.parseLong(value) * 1000; } catch(final NumberFormatException ignore) { } } } return -1; } }
Keep-Alive
相关推荐
HttpClient 4.0引入了多路复用(HTTP/1.1的连接池)功能,极大地提高了性能。连接池允许重用已经建立的TCP连接,减少了建立新连接的开销,尤其在处理大量并发请求时效果显著。此外,HttpClient 4.0还支持异步操作,...
HttpClient 4.0 强化了连接管理,包括连接池的使用和重用,这有助于提高性能并减少服务器压力。`PoolingHttpClientConnectionManager` 可以配置最大连接数、每个路由的最大连接数等,还可以设置超时和自动回收策略。...
HTTPClient是Apache软件基金会的一个开源Java库,它提供了一个强大的、功能丰富的支持HTTP协议的客户端编程工具包。...在实际使用过程中,还需要注意线程安全、连接池管理等问题,以确保程序的稳定性和性能。
1. **连接池管理**:通过`PoolingClientConnectionManager`,HttpClient可以复用TCP连接,提高性能。 2. **认证机制**:支持多种认证方式,如Basic、Digest、NTLM和Kerberos,源码中这部分涉及`CredentialsProvider...
- 多种连接管理策略,如单一连接、多线程连接池 - 支持Cookie管理,处理会话保持 - 支持HTTP基本认证、NTLM认证、Kerberos认证等多种认证机制 - 支持HTTP代理和隧道穿透 - 提供了POST、PUT、DELETE等HTTP方法 ...
HttpClient 4.0 提供了对 HTTP 协议的全面支持,包括 GET、POST、PUT、DELETE 等方法,以及 Cookie 管理、重定向处理、连接池管理等高级功能。它以模块化的设计允许开发者根据需求选择使用不同的组件,提高了代码的...
- **管理连接和连接管理器**: 连接管理器负责维护连接池,管理连接的生命周期。 - **简单连接管理器**: 提供了简单的连接管理功能。 - **连接池管理器**: 用于高效地管理和重用连接。 - **连接管理器关闭**: 正确...
1. 创建HttpClient实例:根据项目需求,可以设置连接池、超时时间、重试策略等。 ```java CloseableHttpClient httpClient = HttpClients.createDefault(); ``` 2. 构建请求:创建HttpGet或HttpPost对象,设置URL...
HttpClient的`PoolingHttpClientConnectionManager`实现了连接池,可以有效地复用TCP连接,提高性能。`CloseableHttpClient`接口提供了关闭连接的方法,以释放系统资源。 HttpClient还提供了多种认证机制。例如,`...
2. **设置连接管理器**:HttpClient支持连接池管理,可以使用`PoolingHttpClientConnectionManager`来复用和管理HTTP连接,提高性能。 3. **创建HttpGet/HttpPost等请求对象**:根据需要,我们可以创建`HttpGet`、`...
HttpClient是一个灵活且强大的HTTP客户端API,它允许开发者执行各种HTTP方法(如GET、POST等),处理响应,以及管理连接池。要创建一个简单的HttpClient实例,你需要以下步骤: 1. 引入Apache HttpClient库: 在你...
1. 创建HttpClient实例,可以设置连接池、超时时间等参数。 2. 构建HttpHost对象,指定请求的目标服务器。 3. 使用HttpGet或HttpPost等创建请求对象,设置请求URL、请求头和请求体。 4. 将请求对象执行(execute)...
8. **性能优化**:HttpClient 4.0-beta2版本在性能上进行了优化,包括连接池的改进、内存管理的优化等,使得在网络通信中能更好地控制资源。 9. **可扩展性**:HttpClient 的设计考虑了插件化,允许用户根据需求...
例如,它支持多线程、连接池管理、重试策略、身份验证和压缩等高级特性。 使用HttpClient,你可以轻松地模拟GET请求。GET请求通常用于从服务器获取资源,比如网页或API数据。以下是一个简单的示例: ```java ...
1. **连接管理**:HTTPCore 4.0引入了连接池的概念,允许复用HTTP连接,减少了建立新连接的开销,提高了性能。同时,它支持多种连接策略,如预连接、保持连接等。 2. **请求和响应处理**:HTTPCore提供了对HTTP请求...
2. **多路复用与HTTP/1.1**:HttpClient 4.x支持HTTP/1.1的连接池,通过Keep-Alive优化连接使用,减少了建立和关闭连接的开销,提升了性能。 3. **异步与同步接口**:HttpClient 4.x提供了同步和异步两种执行模型,...
- **池化连接管理器**: 维护连接池,提高性能。 - **连接管理器关闭**: 清理所有连接资源。 - **连接管理参数**: 配置连接管理行为。 - **多线程请求执行**: 支持并发请求。 - **连接驱逐策略**: 当连接空闲时...
- 涉及HTTP连接管理器,如托管连接和连接管理器的区别、简单连接管理器、连接池管理器以及管理器关闭操作。 - 多线程请求执行、连接驱逐策略、保持连接策略和连接套接字工厂的自定义。 5. SSL/TLS定制和主机名...
对于大型应用,HttpClient的连接池管理也是其强大之处,可以有效地控制和重用TCP连接,避免频繁的建立和关闭连接带来的开销。 关于"标签"中的"httpclient.jar",这是HttpClient库的旧版命名方式,通常指的是早期的...