1919import com .squareup .okhttp .logging .HttpLoggingInterceptor ;
2020import com .squareup .okhttp .logging .HttpLoggingInterceptor .Level ;
2121import com .volcengine .auth .Authentication ;
22+ import com .volcengine .auth .CredentialProvider ;
23+ import com .volcengine .endpoint .DefaultEndpointProvider ;
24+ import com .volcengine .endpoint .EndpointResolver ;
25+ import com .volcengine .interceptor .*;
2226import com .volcengine .model .AbstractResponse ;
2327import com .volcengine .model .ResponseMetadata ;
2428import com .volcengine .sign .Credentials ;
@@ -84,14 +88,27 @@ public class ApiClient {
8488
8589 private Credentials credentials ;
8690 private String region ;
87- private String endpoint = "open.volcengineapi.com" ;
91+ private String endpoint ;
8892 private boolean disableSSL = false ;
8993
94+ private InterceptorChain interceptorChain = new InterceptorChain ();
95+
96+ private EndpointResolver endpointResolver ;
97+
98+ private CredentialProvider credentialProvider ;
99+
100+ private Integer maxIdleConns = 5 ;
101+
102+ private Integer keepAliveDurationMs = 5 * 60 * 1000 ;
103+
104+
90105 /*
91106 * Constructor for ApiClient
92107 */
93108 public ApiClient () {
109+ ConnectionPool connectionPool =new ConnectionPool (maxIdleConns ,keepAliveDurationMs );
94110 httpClient = new OkHttpClient ();
111+ httpClient .setConnectionPool (connectionPool );
95112
96113
97114 verifyingSsl = true ;
@@ -106,6 +123,13 @@ public ApiClient() {
106123 authentications .put (DefaultAuthentication , new VolcstackSign ());
107124 // Prevent the authentications from being modified.
108125 authentications = Collections .unmodifiableMap (authentications );
126+ endpointResolver = new DefaultEndpointProvider ();
127+
128+ interceptorChain .appendRequestInterceptor (new ResolveEndpointInterceptor ());
129+ interceptorChain .appendRequestInterceptor (new BuildRequestInterceptor ());
130+ interceptorChain .appendRequestInterceptor (new SignRequestInterceptor ());
131+
132+ interceptorChain .appendResponseInterceptor (new DeserializedResponseInterceptor ());
109133 }
110134
111135 /**
@@ -891,10 +915,24 @@ public <T> ApiResponse<T> execute(Call call) throws ApiException {
891915 * @throws ApiException If fail to execute the call
892916 */
893917 public <T > ApiResponse <T > execute (Call call , final Type returnType , boolean ... isCommon ) throws ApiException {
918+ if (!(call instanceof InterceptorContext )) {
919+ throw new ApiException ("not support custom context class" );
920+ }
921+ InterceptorContext context = (InterceptorContext ) call ;
922+ ResponseInterceptorContext responseInterceptorContext = new ResponseInterceptorContext ();
923+ responseInterceptorContext .setCommon (isCommon .length > 0 && isCommon [0 ]);
924+ responseInterceptorContext .setReturnType (returnType );
925+ context .setResponseContext (responseInterceptorContext );
926+
927+ context .setApiClient (this );
928+
894929 try {
895- Response response = call .execute ();
896- T data = handleResponse (response , returnType , isCommon );
897- return new ApiResponse <T >(response .code (), response .headers ().toMultimap (), data );
930+ this .interceptorChain .executeRequest (context );
931+ Call finalCall = context .requestContext .getCall ();
932+ Response response = finalCall .execute ();
933+ context .getResponseContext ().setOriginalResponse (response );
934+ this .interceptorChain .executeResponse (context );
935+ return new ApiResponse <T >(response .code (), response .headers ().toMultimap (), (T ) context .getResponseContext ().getData ());
898936 } catch (IOException e ) {
899937 throw new ApiException (e );
900938 }
@@ -922,7 +960,23 @@ public <T> void executeAsync(Call call, ApiCallback<T> callback) {
922960 */
923961 @ SuppressWarnings ("unchecked" )
924962 public <T > void executeAsync (Call call , final Type returnType , final ApiCallback <T > callback ) {
925- call .enqueue (new Callback () {
963+ if (!(call instanceof InterceptorContext )) {
964+ callback .onFailure (new ApiException ("not support custom context class" ), 0 , null );
965+ return ;
966+ }
967+ final InterceptorContext context = (InterceptorContext ) call ;
968+ ResponseInterceptorContext responseInterceptorContext = new ResponseInterceptorContext ();
969+ responseInterceptorContext .setReturnType (returnType );
970+ context .setResponseContext (responseInterceptorContext );
971+
972+ context .setApiClient (this );
973+ try {
974+ this .interceptorChain .executeRequest (context );
975+ } catch (ApiException e ) {
976+ callback .onFailure (e , 0 , null );
977+ return ;
978+ }
979+ Callback okHttpCallBack = new Callback () {
926980 @ Override
927981 public void onFailure (Request request , IOException e ) {
928982 callback .onFailure (new ApiException (e ), 0 , null );
@@ -932,14 +986,18 @@ public void onFailure(Request request, IOException e) {
932986 public void onResponse (Response response ) throws IOException {
933987 T result ;
934988 try {
935- result = (T ) handleResponse (response , returnType );
989+ context .getResponseContext ().setOriginalResponse (response );
990+ context .getApiClient ().interceptorChain .executeResponse (context );
991+ result = (T ) context .responseContext .getData ();
936992 } catch (ApiException e ) {
937993 callback .onFailure (e , response .code (), response .headers ().toMultimap ());
938994 return ;
939995 }
940996 callback .onSuccess (result , response .code (), response .headers ().toMultimap ());
941997 }
942- });
998+ };
999+
1000+ ((InterceptorContext ) call ).getRequestContext ().getCall ().enqueue (okHttpCallBack );
9431001 }
9441002
9451003 /**
@@ -998,20 +1056,33 @@ public <T> T handleResponse(Response response, Type returnType, boolean... isCom
9981056 * @return The HTTP call
9991057 * @throws ApiException If fail to serialize the request body object
10001058 */
1001- public Call buildCall (String path , String method , List <Pair > queryParams , List <Pair > collectionQueryParams , Object body , Map <String , String > headerParams , Map <String , Object > formParams , String [] authNames , ProgressRequestBody .ProgressRequestListener progressRequestListener , boolean ... isCommon ) throws ApiException {
1002- Request request = buildRequest (path , method , queryParams , collectionQueryParams , body , headerParams , formParams , authNames , progressRequestListener , isCommon );
1003-
1004- return httpClient .newCall (request );
1005- }
1006-
1007- private void getDefaultContentType (Map <String , String > headerParams ) {
1059+ public InterceptorContext buildCall (String path , String method , List <Pair > queryParams , List <Pair > collectionQueryParams , Object body , Map <String , String > headerParams , Map <String , Object > formParams , String [] authNames , ProgressRequestBody .ProgressRequestListener progressRequestListener , boolean ... isCommon ) throws ApiException {
1060+ InterceptorContext interceptorContext = new InterceptorContext (this .httpClient , null );
1061+ InitInterceptorContext requestInterceptorContext = new InitInterceptorContext .Builder ()
1062+ .path (path )
1063+ .method (method )
1064+ .queryParams (queryParams )
1065+ .collectionQueryParams (collectionQueryParams )
1066+ .body (body )
1067+ .headerParams (headerParams )
1068+ .formParams (formParams )
1069+ .authNames (authNames )
1070+ .progressRequestListener (progressRequestListener )
1071+ .isCommon (isCommon .length > 0 && isCommon [0 ])
1072+ .build ();
1073+ interceptorContext .setInitInterceptorContext (requestInterceptorContext );
1074+ interceptorContext .setApiClient (this );
1075+ return interceptorContext ;
1076+ }
1077+
1078+ public void getDefaultContentType (Map <String , String > headerParams ) {
10081079 String contentType = headerParams .get ("Content-Type" );
10091080 if (contentType == null ) {
10101081 headerParams .put ("Content-Type" , "text/plain" );
10111082 }
10121083 }
10131084
1014- private boolean isApplicationJsonBody (Map <String , String > headerParams ) {
1085+ public boolean isApplicationJsonBody (Map <String , String > headerParams ) {
10151086 String contentType = headerParams .get ("Content-Type" );
10161087 if (contentType == null ) {
10171088 return false ;
@@ -1022,7 +1093,7 @@ private boolean isApplicationJsonBody(Map<String, String> headerParams) {
10221093 return false ;
10231094 }
10241095
1025- private boolean isPostBody (Map <String , String > headerParams ) {
1096+ public boolean isPostBody (Map <String , String > headerParams ) {
10261097 String contentType = headerParams .get ("Content-Type" );
10271098 if (contentType == null ) {
10281099 return false ;
@@ -1033,12 +1104,12 @@ private boolean isPostBody(Map<String, String> headerParams) {
10331104 return false ;
10341105 }
10351106
1036- private void updateQueryParams (List <Pair > queryParams , String [] param ) {
1107+ public void updateQueryParams (List <Pair > queryParams , String [] param ) {
10371108 queryParams .add (new Pair ("Action" , param [1 ]));
10381109 queryParams .add (new Pair ("Version" , param [2 ]));
10391110 }
10401111
1041- private ServiceInfo addPairAndGetServiceInfo (String path , List <Pair > queryParams , Map <String , String > headerParams ) {
1112+ public ServiceInfo addPairAndGetServiceInfo (String path , List <Pair > queryParams , Map <String , String > headerParams ) {
10421113 String [] param = path .split ("/" );
10431114
10441115 if (param .length >= 6 ) {
@@ -1053,7 +1124,7 @@ private ServiceInfo addPairAndGetServiceInfo(String path, List<Pair> queryParams
10531124
10541125 }
10551126
1056- private String getTruePath (String path , Map <String , String > headerParams ) {
1127+ public String getTruePath (String path , Map <String , String > headerParams ) {
10571128 if (isApplicationJsonBody (headerParams ) || isPostBody (headerParams )) {
10581129 String [] param = path .split ("/" );
10591130 return "/?Action=" + param [1 ] + "&Version=" + param [2 ];
@@ -1088,7 +1159,7 @@ private boolean convertResponseBody(String source, StringBuilder stringBuilder,
10881159 return false ;
10891160 }
10901161
1091- private void buildSimpleRequest (Object body , List <Pair > queryParams , Map <String , String > headerParams , StringBuilder builder , FormEncodingBuilder formBuilder , String chain , boolean ... isCommon ) throws Exception {
1162+ public void buildSimpleRequest (Object body , List <Pair > queryParams , Map <String , String > headerParams , StringBuilder builder , FormEncodingBuilder formBuilder , String chain , boolean ... isCommon ) throws Exception {
10921163 if (body == null ) {
10931164 return ;
10941165 }
@@ -1352,6 +1423,25 @@ public String buildUrl(String path, List<Pair> queryParams, List<Pair> collectio
13521423 return url .toString ();
13531424 }
13541425
1426+ public void buildQueryParams (String path , StringBuilder url , List <Pair > queryParams ) {
1427+ if (queryParams != null && !queryParams .isEmpty ()) {
1428+ // support (constant) query string in `path`, e.g. "/posts?draft=1"
1429+ String prefix = path .contains ("?" ) ? "&" : "?" ;
1430+ for (Pair param : queryParams ) {
1431+ if (param .getValue () != null ) {
1432+ if (prefix != null ) {
1433+ url .append (prefix );
1434+ prefix = null ;
1435+ } else {
1436+ url .append ("&" );
1437+ }
1438+ String value = parameterToString (param .getValue ());
1439+ url .append (escapeString (param .getName ())).append ("=" ).append (escapeString (value ));
1440+ }
1441+ }
1442+ }
1443+ }
1444+
13551445 /**
13561446 * Set header parameters to the request builder, including default headers.
13571447 *
@@ -1369,6 +1459,14 @@ public void processHeaderParams(Map<String, String> headerParams, Request.Builde
13691459 }
13701460 }
13711461
1462+ public void processDefaultHeader (Map <String , String > headerParams ) {
1463+ for (Entry <String , String > header : defaultHeaderMap .entrySet ()) {
1464+ if (!headerParams .containsKey (header .getKey ())) {
1465+ headerParams .put (header .getKey (), parameterToString (header .getValue ()));
1466+ }
1467+ }
1468+ }
1469+
13721470 /**
13731471 * Update query and header parameters based on authentication settings.
13741472 *
@@ -1522,6 +1620,7 @@ public boolean verify(String hostname, SSLSession session) {
15221620 }
15231621 }
15241622
1623+
15251624 private KeyStore newEmptyKeyStore (char [] password ) throws GeneralSecurityException {
15261625 try {
15271626 KeyStore keyStore = KeyStore .getInstance (KeyStore .getDefaultType ());
@@ -1531,4 +1630,43 @@ private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityExcepti
15311630 throw new AssertionError (e );
15321631 }
15331632 }
1633+
1634+ public CredentialProvider getCredentialProvider () {
1635+ return credentialProvider ;
1636+ }
1637+
1638+ public ApiClient setCredentialProvider (CredentialProvider credentialProvider ) {
1639+ this .credentialProvider = credentialProvider ;
1640+ return this ;
1641+ }
1642+
1643+ public EndpointResolver getEndpointResolver () {
1644+ return endpointResolver ;
1645+ }
1646+
1647+ public ApiClient setEndpointResolver (EndpointResolver endpointResolver ) {
1648+ this .endpointResolver = endpointResolver ;
1649+ return this ;
1650+ }
1651+
1652+
1653+ public Integer getMaxIdleConns () {
1654+ return maxIdleConns ;
1655+ }
1656+
1657+ public ApiClient setMaxIdleConns (Integer maxIdleConns ) {
1658+ this .maxIdleConns = maxIdleConns ;
1659+ this .httpClient .setConnectionPool (new ConnectionPool (maxIdleConns ,keepAliveDurationMs ));
1660+ return this ;
1661+ }
1662+
1663+ public Integer getKeepAliveDurationMs () {
1664+ return keepAliveDurationMs ;
1665+ }
1666+
1667+ public ApiClient setKeepAliveDurationMs (Integer keepAliveDurationMs ) {
1668+ this .keepAliveDurationMs = keepAliveDurationMs ;
1669+ this .httpClient .setConnectionPool (new ConnectionPool (maxIdleConns ,keepAliveDurationMs ));
1670+ return this ;
1671+ }
15341672}
0 commit comments