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

com.ksyun.ks3.http.HttpClientFactory Maven / Gradle / Ivy


package com.ksyun.ks3.http;

import java.lang.reflect.Method;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.ProtocolException;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.ChallengeState;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.params.ConnRoutePNames;
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.conn.ssl.SSLContexts;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.config.SocketConfig;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.client.config.RequestConfig;
import com.ksyun.ks3.exception.Ks3ClientException;
import com.ksyun.ks3.http.internal.Ks3DnsResolver;
import com.ksyun.ks3.utils.StringUtils;

/**
 * @author lijunwei[[email protected]]  
 * 
 * @date 2014年10月14日 下午8:05:52
 * 
 * @description
 **/
public class HttpClientFactory {

	private final Log log = LogFactory.getLog(this.getClass());
	public HttpClient createHttpClient(HttpClientConfig config) {
		
		/*初始化配置*/
		SocketConfig soConfig = SocketConfig.custom()
				//.setSoTimeout(config.getInt(ClientConfig.SOCKET_TIMEOUT))
				.setTcpNoDelay(true)
				.build();
		int socketSendBufferSizeHint = config.getSocketSendBufferSizeHint();
		int socketReceiveBufferSizeHint = config.getSocketReceiveBufferSizeHint();
		int buffersize = 0;
		if (socketSendBufferSizeHint > 0 || socketReceiveBufferSizeHint > 0) {
			buffersize = Math.max(socketSendBufferSizeHint, socketReceiveBufferSizeHint);
		}
		ConnectionConfig coConfig = ConnectionConfig.custom()
				.setBufferSize(buffersize)
				.build();
		//==解决httpclient4.5.7以后版本会重新编解码uri造成签名失败的问题(exclude:4.5.7,未开放相关接口)
		RequestConfig reConfig =null;
		RequestConfig.Builder builder=RequestConfig.custom()
				.setConnectTimeout(config.getConnectionTimeOut())
				.setSocketTimeout(config.getSocketTimeOut())
				.setStaleConnectionCheckEnabled(true);
		try {
			if(RequestConfig.class.getDeclaredField("normalizeUri")!=null){
				Method me=RequestConfig.Builder.class.getDeclaredMethod("setNormalizeUri",boolean.class);
				me.invoke(builder,false);
            }
		} catch (Exception e) {
		}
		reConfig=builder.build();
		//==END
		PlainConnectionSocketFactory sf = PlainConnectionSocketFactory.getSocketFactory();
		SSLContext sslContext;
		SSLConnectionSocketFactory sslsf = null;
		try {
			sslContext = SSLContexts.custom().build();
			String version0 = System.getProperty("java.specification.version");
			float version = 0f;
			try{
				version = Float.valueOf(version0);
			}catch(Exception e){}
			if(version >= 1.7f){
				log.debug("java version "+version+", use STRICT_HOSTNAME_VERIFIER");
				sslsf = new SSLConnectionSocketFactory(sslContext,SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER);
			}
			else{
				log.debug("java version "+version+", use BROWSER_COMPATIBLE_HOSTNAME_VERIFIER");
				sslsf = new SSLConnectionSocketFactory(sslContext,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
			}
		} catch (Exception e) {
			throw new Ks3ClientException("Unable to access default SSL context",e);
		}

		Registry r = RegistryBuilder. create().register("http", sf).register("https", sslsf).build();

		PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(r
				,null,null,Ks3DnsResolver.INSTANCE,config.getConnectionTTL(), TimeUnit.MILLISECONDS);
		connectionManager.setMaxTotal(config.getMaxConnections());
		connectionManager.setDefaultMaxPerRoute(config.getMaxPerRoute());
		connectionManager.setDefaultConnectionConfig(coConfig);
		connectionManager.setDefaultSocketConfig(soConfig);
		
		/* Set proxy if configured */
		String proxyHost = config.getProxyHost();
		int proxyPort = config.getProxyPort();
		
		
		CloseableHttpClient httpClient = null;
		if (proxyHost != null && proxyPort > 0) {

			HttpHost proxyHttpHost = new HttpHost(proxyHost, proxyPort);
			String proxyUsername = config.getProxyUserName();
			String proxyPassword = config.getProxyPassWord();
			String proxyDomain = config.getProxyDomain();
			String proxyWorkstation = config.getProxyWorkStation();
			
			BasicCredentialsProvider creprovide = null;
			if (proxyUsername != null && proxyPassword != null) {
				creprovide = new BasicCredentialsProvider();
				creprovide.setCredentials(new AuthScope(proxyHost, proxyPort),new NTCredentials(proxyUsername, proxyPassword, proxyWorkstation, proxyDomain));
			}
			HttpRequestInterceptor interceptor = null;
			if (config.isPreemptiveBasicProxyAuth()){
				interceptor = new PreemptiveProxyAuth(proxyHttpHost);
			}
			DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxyHttpHost);
			
			httpClient = HttpClients.custom().setConnectionManager(connectionManager).setRedirectStrategy(new NeverFollowRedirectStrategy())
					.setRetryHandler(new DefaultHttpRequestRetryHandler(config.getMaxRetry(), false))
					.setDefaultRequestConfig(reConfig)
					.setRoutePlanner(routePlanner)
					.setDefaultCredentialsProvider(creprovide)
					.addInterceptorFirst(interceptor)
					.build();
			

		} else {
			httpClient = HttpClients.custom().setConnectionManager(connectionManager).setRedirectStrategy(new NeverFollowRedirectStrategy())
					.setRetryHandler(new DefaultHttpRequestRetryHandler(config.getMaxRetry(), false))
					.setDefaultRequestConfig(reConfig)
					.build();
		}

		return httpClient;
	}

	private static final class NeverFollowRedirectStrategy  extends DefaultRedirectStrategy {

		  @Override
	        public boolean isRedirected(HttpRequest request, HttpResponse response,
	                HttpContext context) throws ProtocolException {
	            return false;
	        }

	        @Override
	        public HttpUriRequest getRedirect(HttpRequest request,
	                HttpResponse response, HttpContext context)
	                throws ProtocolException {
	            return null;
	        }
	}

	/**
	 * HttpRequestInterceptor implementation to set up pre-emptive
	 * authentication against a defined basic proxy server.
	 */
	private static class PreemptiveProxyAuth implements HttpRequestInterceptor {

		private final HttpHost proxyHost;


		public PreemptiveProxyAuth ( HttpHost proxyHost ) {

			this.proxyHost = proxyHost;
		}


		public void process(HttpRequest request, HttpContext context) {

			AuthCache authCache;
			// Set up the a Basic Auth scheme scoped for the proxy - we don't
			// want to do this for non-proxy authentication.
			BasicScheme basicScheme = new BasicScheme(ChallengeState.PROXY);

			if (context.getAttribute(ClientContext.AUTH_CACHE) == null) {
				authCache = new BasicAuthCache();
				authCache.put(this.proxyHost, basicScheme);
				context.setAttribute(ClientContext.AUTH_CACHE, authCache);
			} else {
				authCache = (AuthCache) context.getAttribute(ClientContext.AUTH_CACHE);
				authCache.put(this.proxyHost, basicScheme);
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy