package com.aliyun.mq.http.common.http; import com.aliyun.mq.http.common.ClientException; import com.aliyun.mq.http.common.HttpMethod; import com.aliyun.mq.http.common.utils.HttpHeaders; import com.aliyun.mq.http.common.utils.VersionInfoUtils; import com.aliyun.mq.http.common.comm.ExecutionContext; import com.aliyun.mq.http.common.comm.RepeatableInputStreamEntity; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.NTCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.config.AuthSchemes; import org.apache.http.client.config.CookieSpecs; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.*; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; import org.apache.http.impl.nio.client.HttpAsyncClients; import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager; import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor; import org.apache.http.impl.nio.reactor.IOReactorConfig; import org.apache.http.nio.conn.NHttpClientConnectionManager; import org.apache.http.nio.reactor.ConnectingIOReactor; import org.apache.http.nio.reactor.IOReactorException; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; /** * The factory to create HTTP-related objects. */ public class HttpFactory { private static SSLConnectionSocketFactory getSSLSocketFactory() { TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) { } }}; try { SSLContext sslcontext = SSLContext.getInstance("SSL"); sslcontext.init(null, trustAllCerts, null); SSLConnectionSocketFactory ssf = new SSLConnectionSocketFactory( sslcontext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); return ssf; } catch (Exception e) { throw new RuntimeException(e); } } public static PoolingNHttpClientConnectionManager createConnectionManager(ClientConfiguration config) { // Set HTTP params. // Create I/O reactor configuration IOReactorConfig ioReactorConfig = IOReactorConfig.custom() .setIoThreadCount(config.getIoReactorThreadCount()) .setConnectTimeout(config.getConnectionTimeout()) .setSoTimeout(config.getSocketTimeout()) .setSoKeepAlive(config.isSoKeepAlive()).build(); // Create a custom I/O reactort ConnectingIOReactor ioReactor; try { ioReactor = new DefaultConnectingIOReactor(ioReactorConfig); } catch (IOReactorException e) { throw new RuntimeException(e); } PoolingNHttpClientConnectionManager connManager = new PoolingNHttpClientConnectionManager( ioReactor); connManager.setDefaultMaxPerRoute(config.getMaxConnectionsPerRoute()); connManager.setMaxTotal(config.getMaxConnections()); return connManager; } public static CloseableHttpAsyncClient createHttpAsyncClient( PoolingNHttpClientConnectionManager connManager, ClientConfiguration config) { HttpAsyncClientBuilder httpClientBuilder = HttpAsyncClients.custom() .setConnectionManager(connManager); // Set proxy if set. String proxyHost = config.getProxyHost(); int proxyPort = config.getProxyPort(); if (proxyHost != null && proxyPort > 0) { HttpHost proxy = new HttpHost(proxyHost, proxyPort); httpClientBuilder.setProxy(proxy); String proxyUsername = config.getProxyUsername(); String proxyPassword = config.getProxyPassword(); if (proxyUsername != null && proxyPassword != null) { String proxyDomain = config.getProxyDomain(); String proxyWorkstation = config.getProxyWorkstation(); CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(new AuthScope(proxy), new NTCredentials(proxyUsername, proxyPassword, proxyWorkstation, proxyDomain) ); httpClientBuilder .setDefaultCredentialsProvider(credentialsProvider); } } RequestConfig defaultRequestConfig = RequestConfig .custom() .setCookieSpec(CookieSpecs.BEST_MATCH) .setExpectContinueEnabled(true) .setStaleConnectionCheckEnabled(true) .setTargetPreferredAuthSchemes( Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST)) .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC)) .setConnectTimeout(config.getConnectionTimeout()) .setSocketTimeout(config.getSocketTimeout()) .setExpectContinueEnabled(config.isExceptContinue()).build(); httpClientBuilder.setDefaultRequestConfig(defaultRequestConfig); httpClientBuilder .setMaxConnPerRoute(config.getMaxConnectionsPerRoute()); httpClientBuilder.setMaxConnTotal(config.getMaxConnections()); httpClientBuilder.setUserAgent(VersionInfoUtils.getDefaultUserAgent()); CloseableHttpAsyncClient httpclient = httpClientBuilder.build(); return httpclient; } public static HttpRequestBase createHttpRequest(ServiceClient.Request request, ExecutionContext context) { String uri = request.getUri(); HttpMethod method = request.getMethod(); HttpRequestBase httpRequest; if (method == HttpMethod.POST) { // POST HttpPost postMethod = new HttpPost(uri); if (request.getContent() != null) { postMethod.setEntity(new RepeatableInputStreamEntity(request)); } httpRequest = postMethod; } else if (method == HttpMethod.PUT) { // PUT HttpPut putMethod = new HttpPut(uri); if (request.getContent() != null) { putMethod.setEntity(new RepeatableInputStreamEntity(request)); } httpRequest = putMethod; } else if (method == HttpMethod.GET) { // GET httpRequest = new HttpGet(uri); } else if (method == HttpMethod.DELETE) { // DELETE //httpRequest = new HttpDelete(uri); // support body in Delete HttpDeleteWrapper deleteMethod = new HttpDeleteWrapper(uri); if (request.getContent() != null) { deleteMethod.setEntity(new RepeatableInputStreamEntity(request)); } httpRequest = deleteMethod; } else if (method == HttpMethod.HEAD) { httpRequest = new HttpHead(uri); } else if (method == HttpMethod.OPTIONS) { httpRequest = new HttpOptions(uri); } else { throw new IllegalArgumentException(String.format( "Unsupported HTTP method: %s.", request.getMethod() .toString() )); } configureRequestHeaders(request, context, httpRequest); // httpRequest.addHeader("User-Agent","aliyun-java-sdk"); return httpRequest; } private static void configureRequestHeaders(ServiceClient.Request request, ExecutionContext context, HttpRequestBase httpRequest) { // Copy headers in the request message to the HTTP request for (Entry<String, String> entry : request.getHeaders().entrySet()) { // HttpClient fills in the Content-Length, // and complains if add it again, so skip it as well as the Host // header. if (entry.getKey().equalsIgnoreCase(HttpHeaders.CONTENT_LENGTH) || entry.getKey().equalsIgnoreCase(HttpHeaders.HOST)) { continue; } httpRequest.addHeader(entry.getKey(), entry.getValue()); } // Set content type and encoding // if (httpRequest.getHeaders(HttpHeaders.CONTENT_TYPE) == null || // httpRequest.getHeaders(HttpHeaders.CONTENT_TYPE).length == 0){ // httpRequest.addHeader(HttpHeaders.CONTENT_TYPE, // "application/x-www-form-urlencoded; " + // "charset=" + context.getCharset().toLowerCase()); // } } public static class IdleConnectionMonitor extends Thread { private static final IdleConnectionMonitor instance = new IdleConnectionMonitor(); private final List<NHttpClientConnectionManager> connMgrs = new ArrayList<NHttpClientConnectionManager>(); private volatile boolean shutdown = false; private int CONNECTION_MANAGER_LIMIT = 50; private IdleConnectionMonitor() { this.setName("IdleConnectionMonitorThread"); this.setDaemon(true); this.start(); } public static IdleConnectionMonitor getInstance() { return instance; } public void addConnMgr(NHttpClientConnectionManager connMgr) { synchronized (connMgrs) { if (CONNECTION_MANAGER_LIMIT > 0 && connMgrs.size() > CONNECTION_MANAGER_LIMIT) { throw new ClientException("Too Many ServiceClient created.", null); } connMgrs.add(connMgr); } } public void removeConnMgr(NHttpClientConnectionManager connMgr) { synchronized (connMgrs) { connMgrs.remove(connMgr); } } public void set_CONNECTION_MANAGER_LIMIT(int limit) { this.CONNECTION_MANAGER_LIMIT = limit; } @Override public void run() { try { while (!shutdown) { sleep(15000); List<NHttpClientConnectionManager> tmpConnMgrs; synchronized (connMgrs) { tmpConnMgrs = new ArrayList<NHttpClientConnectionManager>(connMgrs); } for (NHttpClientConnectionManager connMgr : tmpConnMgrs) { // Close expired connections connMgr.closeExpiredConnections(); // Optionally, close connections // that have been idle longer than 60 sec connMgr.closeIdleConnections(60, TimeUnit.SECONDS); } } } catch (InterruptedException ex) { // terminate } } synchronized public void shutdown() { shutdown = true; } } }