package com.workshare.msnos.core.protocols.ip; import java.io.IOException; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.DnsResolver; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.workshare.msnos.soup.ShutdownHooks; import com.workshare.msnos.soup.ShutdownHooks.Hook; import com.workshare.msnos.soup.net.DnsResolverWithTimeout; public class HttpClientFactory { private static final Logger log = LoggerFactory.getLogger(HttpClientFactory.class); private static HttpClient shared; /** * The singleton is built this way because of the crappy implementation * of the Powemock cglib :( [bb] * (I knew I should not have used it) * @see MicroserviceLocationTest */ public synchronized static HttpClient sharedHttpClient() { if (shared == null) shared = newHttpClient(); return shared; } public static HttpClient newHttpClient() { final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(getDefaultRegistry(), getDnsResolver()); cm.setMaxTotal(getHttpMaxTotalConnections()); cm.setDefaultMaxPerRoute(getHttpMaxDefaultConnectionsPerRoute()); final RequestConfig config = RequestConfig.custom() .setSocketTimeout(getHttpConnectTimeout()) .setConnectTimeout(getHttpSocketTimeout()) .build(); final CloseableHttpClient httpClient = HttpClients.custom() .setDefaultRequestConfig(config) .setConnectionManager(cm) .setUserAgent(getHttpUserAgent()) .build(); ShutdownHooks.addHook(new Hook(){ @Override public void run() { try { log.info("Shutting down HTTP client..."); httpClient.close(); } catch (IOException ex) { log.debug("Error closing HTTP client", ex); } finally { log.info("done!"); } } @Override public String name() { return "HTTP client closing"; } @Override public int priority() { return Integer.MIN_VALUE; }}); return httpClient; } public static String getHttpUserAgent() { return System.getProperty("com.ws.msnos.http.user-agent", "com.msnos.client-v1.0"); } public static int getHttpSocketTimeout() { return Integer.getInteger("com.ws.msnos.http.timeout.socket", 10000); } public static int getHttpConnectTimeout() { return Integer.getInteger("com.ws.msnos.http.timeout.connection", 10000); } public static int getHttpMaxTotalConnections() { return Integer.getInteger("com.ws.msnos.http.max.total.connection.num", 200); } public static int getHttpMaxDefaultConnectionsPerRoute() { return Integer.getInteger("com.ws.msnos.http.max.route.connection.num", 200); } private static Registry<ConnectionSocketFactory> getDefaultRegistry() { return RegistryBuilder.<ConnectionSocketFactory>create() .register("https", SSLConnectionSocketFactory.getSocketFactory()) .register("http", PlainConnectionSocketFactory.getSocketFactory()) .build(); } private static DnsResolver getDnsResolver() { return new DnsResolverWithTimeout(); } }