All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.helger.httpclient.HttpClientFactory Maven / Gradle / Ivy

/**
 * Copyright (C) 2016 Philip Helger (www.helger.com)
 * philip[at]helger[dot]com
 *
 * Licensed 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.
 */
package com.helger.httpclient;

import java.nio.charset.CodingErrorAction;
import java.security.GeneralSecurityException;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import javax.net.ssl.SSLContext;

import org.apache.http.HttpHost;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.protocol.RequestAcceptEncoding;
import org.apache.http.client.protocol.RequestAddCookies;
import org.apache.http.client.protocol.ResponseContentEncoding;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
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.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLInitializationException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import com.helger.commons.annotation.OverrideOnDemand;
import com.helger.commons.charset.CCharset;

/**
 * A factory for creating {@link CloseableHttpClient} that is e.g. to be used in
 * the {@link HttpClientManager}.
 *
 * @author Philip Helger
 */
@Immutable
public class HttpClientFactory
{
  private final SSLContext m_aDefaultSSLContext;

  public HttpClientFactory ()
  {
    this (null);
  }

  public HttpClientFactory (@Nullable final SSLContext aDefaultSSLContext)
  {
    m_aDefaultSSLContext = aDefaultSSLContext;
  }

  /**
   * Create a custom SSLContext to use for the SSL Socket factory.
   *
   * @return null if no custom context is present.
   * @throws GeneralSecurityException
   *         In case key management problems occur.
   */
  @Nullable
  @OverrideOnDemand
  public SSLContext createSSLContext () throws GeneralSecurityException
  {
    return m_aDefaultSSLContext;
  }

  @Nullable
  public LayeredConnectionSocketFactory createSSLFactory ()
  {
    LayeredConnectionSocketFactory aSSLFactory = null;

    // First try with a custom SSL context
    try
    {
      final SSLContext aSSLContext = createSSLContext ();
      if (aSSLContext != null)
        try
        {
          aSSLFactory = new SSLConnectionSocketFactory (aSSLContext,
                                                        new String [] { "TLSv1" },
                                                        null,
                                                        SSLConnectionSocketFactory.getDefaultHostnameVerifier ());
        }
        catch (final SSLInitializationException ex)
        {
          // Fall through
        }
    }
    catch (final GeneralSecurityException ex)
    {
      // Fall through
    }

    if (aSSLFactory == null)
    {
      // No custom SSL context present - use system defaults
      try
      {
        aSSLFactory = SSLConnectionSocketFactory.getSystemSocketFactory ();
      }
      catch (final SSLInitializationException ex)
      {
        try
        {
          aSSLFactory = SSLConnectionSocketFactory.getSocketFactory ();
        }
        catch (final SSLInitializationException ex2)
        {
          // Fall through
        }
      }
    }
    return aSSLFactory;
  }

  @Nonnull
  public ConnectionConfig createConnectionConfig ()
  {
    return ConnectionConfig.custom ()
                           .setMalformedInputAction (CodingErrorAction.IGNORE)
                           .setUnmappableInputAction (CodingErrorAction.IGNORE)
                           .setCharset (CCharset.CHARSET_UTF_8_OBJ)
                           .build ();
  }

  @Nonnull
  public HttpClientConnectionManager createConnectionManager ()
  {
    final LayeredConnectionSocketFactory aSSLFactory = createSSLFactory ();
    if (aSSLFactory == null)
      throw new IllegalStateException ("Failed to create SSL SocketFactory");

    final Registry  sfr = RegistryBuilder. create ()
                                                                  .register ("http",
                                                                             PlainConnectionSocketFactory.getSocketFactory ())
                                                                  .register ("https", aSSLFactory)
                                                                  .build ();

    final PoolingHttpClientConnectionManager aConnMgr = new PoolingHttpClientConnectionManager (sfr);
    aConnMgr.setDefaultMaxPerRoute (100);
    aConnMgr.setMaxTotal (200);
    aConnMgr.setValidateAfterInactivity (1000);
    final ConnectionConfig aConnectionConfig = createConnectionConfig ();
    aConnMgr.setDefaultConnectionConfig (aConnectionConfig);
    return aConnMgr;
  }

  @Nonnull
  public RequestConfig createRequestConfig ()
  {
    return RequestConfig.custom ()
                        .setCookieSpec (CookieSpecs.DEFAULT)
                        .setSocketTimeout (10000)
                        .setConnectTimeout (5000)
                        .setConnectionRequestTimeout (5000)
                        .setCircularRedirectsAllowed (false)
                        .setRedirectsEnabled (true)
                        .build ();
  }

  @Nullable
  public HttpHost createProxyHost ()
  {
    return null;
  }

  @Nonnull
  public HttpClientBuilder createHttpClientBuilder ()
  {
    final HttpClientConnectionManager aConnMgr = createConnectionManager ();
    final RequestConfig aRequestConfig = createRequestConfig ();
    final HttpHost aProxy = createProxyHost ();

    final HttpClientBuilder aHCB = HttpClients.custom ()
                                              .setConnectionManager (aConnMgr)
                                              .setDefaultRequestConfig (aRequestConfig)
                                              .setProxy (aProxy);
    // Allow gzip,compress
    aHCB.addInterceptorLast (new RequestAcceptEncoding ());
    // Add cookies
    aHCB.addInterceptorLast (new RequestAddCookies ());
    // Un-gzip or uncompress
    aHCB.addInterceptorLast (new ResponseContentEncoding ());
    return aHCB;
  }

  @Nonnull
  public CloseableHttpClient createHttpClient ()
  {
    final HttpClientBuilder aBuilder = createHttpClientBuilder ();
    return aBuilder.build ();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy