2323import java .io .FileInputStream ;
2424import java .io .IOException ;
2525import java .io .InputStream ;
26+ import java .net .InetAddress ;
2627import java .net .URI ;
2728import java .net .URISyntaxException ;
29+ import java .net .UnknownHostException ;
30+ import java .security .NoSuchAlgorithmException ;
31+ import java .security .KeyManagementException ;
32+ import java .security .KeyStoreException ;
33+ import java .util .Arrays ;
34+ import java .util .ArrayList ;
35+ import java .util .Collections ;
36+ import java .util .Date ;
37+ import java .util .Objects ;
2838import java .util .HashMap ;
2939import java .util .List ;
3040import java .util .Map ;
3343import java .util .concurrent .TimeoutException ;
3444import java .util .regex .Matcher ;
3545import java .util .regex .Pattern ;
36- import java .util .Date ;
37- import java .util .Objects ;
3846
3947import com .qcloud .cos .ClientConfig ;
4048import com .qcloud .cos .Headers ;
4149import com .qcloud .cos .auth .COSCredentials ;
4250import com .qcloud .cos .auth .COSSigner ;
51+ import com .qcloud .cos .endpoint .CIRegionEndpointBuilder ;
52+ import com .qcloud .cos .endpoint .CIPicRegionEndpointBuilder ;
4353import com .qcloud .cos .internal .cihandler .HttpEntityEnclosingDelete ;
54+ import com .qcloud .cos .internal .CIPicServiceRequest ;
55+ import com .qcloud .cos .model .ListBucketsRequest ;
4456import com .qcloud .cos .region .Region ;
4557import com .qcloud .cos .event .ProgressInputStream ;
4658import com .qcloud .cos .event .ProgressListener ;
8193import org .apache .http .client .methods .HttpPut ;
8294import org .apache .http .client .methods .HttpRequestBase ;
8395import org .apache .http .client .protocol .HttpClientContext ;
96+ import org .apache .http .config .Registry ;
97+ import org .apache .http .config .RegistryBuilder ;
98+ import org .apache .http .conn .DnsResolver ;
99+ import org .apache .http .conn .socket .ConnectionSocketFactory ;
100+ import org .apache .http .conn .socket .PlainConnectionSocketFactory ;
101+ import org .apache .http .conn .ssl .NoopHostnameVerifier ;
102+ import org .apache .http .ssl .SSLContextBuilder ;
103+ import org .apache .http .conn .ssl .SSLConnectionSocketFactory ;
84104import org .apache .http .entity .InputStreamEntity ;
85105import org .apache .http .impl .client .HttpClientBuilder ;
86106import org .apache .http .impl .client .HttpClients ;
89109import org .slf4j .Logger ;
90110import org .slf4j .LoggerFactory ;
91111
112+ import javax .net .ssl .SSLContext ;
92113
93114public class DefaultCosHttpClient implements CosHttpClient {
94115
@@ -102,13 +123,59 @@ public class DefaultCosHttpClient implements CosHttpClient {
102123 private BackoffStrategy backoffStrategy ;
103124
104125 private CosErrorResponseHandler errorResponseHandler ;
126+ private HandlerAfterProcess handlerAfterProcess ;
105127 private static final Logger log = LoggerFactory .getLogger (DefaultCosHttpClient .class );
106128
107129 public DefaultCosHttpClient (ClientConfig clientConfig ) {
108130 super ();
109131 this .errorResponseHandler = new CosErrorResponseHandler ();
110132 this .clientConfig = clientConfig ;
111- this .connectionManager = new PoolingHttpClientConnectionManager ();
133+ this .handlerAfterProcess = clientConfig .getHandlerAfterProcess ();
134+ DnsResolver dnsResolver = new DnsResolver () {
135+ @ Override
136+ public InetAddress [] resolve (String host ) throws UnknownHostException {
137+ InetAddress [] addresses = InetAddress .getAllByName (host );
138+ List <InetAddress > addressList = new ArrayList <>(Arrays .asList (addresses ));
139+ Collections .shuffle (addressList );
140+
141+ InetAddress [] newAddresses = addressList .toArray (new InetAddress [0 ]);
142+ return newAddresses ;
143+ }
144+ };
145+
146+ if (clientConfig .isCheckSSLCertificate ()) {
147+ if (clientConfig .isUseDefaultDnsResolver ()) {
148+ this .connectionManager = new PoolingHttpClientConnectionManager ();
149+ } else {
150+ Registry <ConnectionSocketFactory > socketFactoryRegistry = RegistryBuilder .<ConnectionSocketFactory > create ()
151+ .register ("http" , PlainConnectionSocketFactory .getSocketFactory ())
152+ .register ("https" , SSLConnectionSocketFactory .getSocketFactory ()).build ();
153+ this .connectionManager = new PoolingHttpClientConnectionManager (socketFactoryRegistry , dnsResolver );
154+ }
155+ } else {
156+ try {
157+ SSLContext sslContext = SSLContextBuilder .create ().loadTrustMaterial ((chain , authType ) -> true ).build ();
158+
159+ SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory (sslContext , NoopHostnameVerifier .INSTANCE );
160+ Registry <ConnectionSocketFactory > socketFactoryRegistry = RegistryBuilder .<ConnectionSocketFactory > create ()
161+ .register ("http" , PlainConnectionSocketFactory .getSocketFactory ())
162+ .register ("https" , sslSocketFactory ).build ();
163+ if (clientConfig .isUseDefaultDnsResolver ()) {
164+ this .connectionManager = new PoolingHttpClientConnectionManager (socketFactoryRegistry );
165+ } else {
166+ this .connectionManager = new PoolingHttpClientConnectionManager (socketFactoryRegistry , dnsResolver );
167+ }
168+ } catch (NoSuchAlgorithmException e ) {
169+ log .error ("fail to init http client: " , e );
170+ throw new RuntimeException (e );
171+ } catch (KeyStoreException e ) {
172+ log .error ("fail to init http client: " , e );
173+ throw new RuntimeException (e );
174+ } catch (KeyManagementException e ) {
175+ log .error ("fail to init http client: " , e );
176+ throw new RuntimeException (e );
177+ }
178+ }
112179 this .maxErrorRetry = clientConfig .getMaxErrorRetry ();
113180 this .retryPolicy = ValidationUtils .assertNotNull (clientConfig .getRetryPolicy (), "retry policy" );
114181 this .backoffStrategy = ValidationUtils .assertNotNull (clientConfig .getBackoffStrategy (), "backoff strategy" );
@@ -496,6 +563,10 @@ public <X, Y extends CosServiceRequest> X exeute(CosHttpRequest<Y> request,
496563 originalContent .mark (readLimit );
497564 }
498565
566+ long startTime = 0 ;
567+ long endTime = 0 ;
568+ int response_status = 0 ;
569+
499570 int retryIndex = 0 ;
500571 while (true ) {
501572 try {
@@ -512,17 +583,24 @@ public <X, Y extends CosServiceRequest> X exeute(CosHttpRequest<Y> request,
512583 originalContent .reset ();
513584 }
514585 if (retryIndex != 0 ) {
586+ response_status = 0 ;
587+ if (clientConfig .IsRefreshEndpointAddr ()) {
588+ refreshEndpointAddr (request );
589+ }
590+
515591 long delay = backoffStrategy .computeDelayBeforeNextRetry (retryIndex );
516592 request .addHeader ("x-cos-sdk-retry" , "true" );
517593 Thread .sleep (delay );
518594 }
519595 HttpContext context = HttpClientContext .create ();
520596 httpRequest = buildHttpRequest (request );
521597 httpResponse = null ;
598+ startTime = System .currentTimeMillis ();
522599 httpResponse = executeRequest (context , httpRequest );
523600 checkResponse (request , httpRequest , httpResponse );
524601 break ;
525602 } catch (CosServiceException cse ) {
603+ response_status = -1 ;
526604 closeHttpResponseStream (httpResponse );
527605 String errorMsg = String .format ("failed to execute http request due to service exception, request timeStamp %d,"
528606 + " httpRequest: %s, retryIdx:%d, maxErrorRetry:%d" , System .currentTimeMillis (), request ,
@@ -540,6 +618,7 @@ public <X, Y extends CosServiceRequest> X exeute(CosHttpRequest<Y> request,
540618 }
541619 changeEndpointForRetry (request , httpResponse , retryIndex );
542620 } catch (CosClientException cce ) {
621+ response_status = -1 ;
543622 closeHttpResponseStream (httpResponse );
544623 String errorMsg = String .format ("failed to execute http request due to client exception, request timeStamp %d,"
545624 + " httpRequest: %s, retryIdx:%d, maxErrorRetry:%d" , System .currentTimeMillis (), request ,
@@ -551,12 +630,15 @@ public <X, Y extends CosServiceRequest> X exeute(CosHttpRequest<Y> request,
551630 }
552631 changeEndpointForRetry (request , httpResponse , retryIndex );
553632 } catch (Exception exp ) {
633+ response_status = -1 ;
554634 String expName = exp .getClass ().getName ();
555635 String errorMsg = String .format ("httpClient execute occur an unknown exception:%s, httpRequest: %s" , expName , request );
556636 closeHttpResponseStream (httpResponse );
557637 log .error (errorMsg , exp );
558638 throw new CosClientException (errorMsg , exp );
559639 } finally {
640+ endTime = System .currentTimeMillis ();
641+ handlerAfterProcess .handle (response_status , endTime - startTime );
560642 ++retryIndex ;
561643 }
562644 }
@@ -705,4 +787,41 @@ private <Y extends CosServiceRequest> void changeEndpointForRetry(CosHttpRequest
705787 }
706788 }
707789 }
790+
791+ private <X extends CosServiceRequest > void refreshEndpointAddr (CosHttpRequest <X > request ) throws CosClientException {
792+ boolean isCIRequest = request .getOriginalRequest () instanceof CIServiceRequest ;
793+ boolean isServiceRequest = request .getOriginalRequest () instanceof ListBucketsRequest ;
794+ String endpoint = "" ;
795+ String endpointAddr = "" ;
796+ if (isServiceRequest ) {
797+ endpoint = clientConfig .getEndpointBuilder ().buildGetServiceApiEndpoint ();
798+ endpointAddr =
799+ clientConfig .getEndpointResolver ().resolveGetServiceApiEndpoint (endpoint );
800+ } else {
801+
802+ if (request .getOriginalRequest () instanceof CIPicServiceRequest ) {
803+ endpoint = new CIPicRegionEndpointBuilder (clientConfig .getRegion ()).buildGeneralApiEndpoint (request .getBucketName ());
804+ } else if (isCIRequest ) {
805+ endpoint = new CIRegionEndpointBuilder (clientConfig .getRegion ()).buildGeneralApiEndpoint (request .getBucketName ());
806+ } else {
807+ endpoint = clientConfig .getEndpointBuilder ().buildGeneralApiEndpoint (request .getBucketName ());
808+ }
809+ endpointAddr = clientConfig .getEndpointResolver ().resolveGeneralApiEndpoint (endpoint );
810+ }
811+
812+ if (endpoint == null ) {
813+ throw new CosClientException ("endpoint is null, please check your endpoint builder" );
814+ }
815+ if (endpointAddr == null ) {
816+ throw new CosClientException (
817+ "endpointAddr is null, please check your endpoint resolver" );
818+ }
819+
820+ String fixedEndpointAddr = request .getOriginalRequest ().getFixedEndpointAddr ();
821+ if (fixedEndpointAddr != null ) {
822+ request .setEndpoint (fixedEndpointAddr );
823+ } else {
824+ request .setEndpoint (endpointAddr );
825+ }
826+ }
708827}
0 commit comments