diff --git a/MIGRATION b/MIGRATION index d5ffda59..c38e264d 100644 --- a/MIGRATION +++ b/MIGRATION @@ -1,3 +1,6 @@ [4.0.9] - ExplorerAndPoolUnspentBoxesLoader moved from package org.ergoplatform.appkit.impl to org.ergoplatform.appkit - DefaultApi.getApiV1AddressesP1Transactions new parameter "concise" - use false for old behaviour +- RestApiErgoClient.createWithProxy method replaced by RestApiErgoClient.createWithHttpClientBuilder + To create an instance using a proxy, use createWithHttpClientBuilder with a Builder created with + new OkHttpClient.Builder().proxy(...) diff --git a/appkit/src/main/java/org/ergoplatform/appkit/RestApiErgoClient.java b/appkit/src/main/java/org/ergoplatform/appkit/RestApiErgoClient.java index a7284503..8f31c10e 100644 --- a/appkit/src/main/java/org/ergoplatform/appkit/RestApiErgoClient.java +++ b/appkit/src/main/java/org/ergoplatform/appkit/RestApiErgoClient.java @@ -1,24 +1,25 @@ package org.ergoplatform.appkit; import com.google.common.base.Strings; + import org.ergoplatform.appkit.config.ErgoNodeConfig; import org.ergoplatform.appkit.impl.BlockchainContextBuilderImpl; import org.ergoplatform.appkit.impl.NodeAndExplorerDataSourceImpl; import org.ergoplatform.explorer.client.ExplorerApiClient; import org.ergoplatform.restapi.client.ApiClient; -import java.net.Proxy; import java.util.function.Function; + import javax.annotation.Nullable; +import okhttp3.OkHttpClient; + /** * This implementation of {@link ErgoClient} uses REST API of Ergo node for communication. */ public class RestApiErgoClient implements ErgoClient { - private final String _nodeUrl; private final NetworkType _networkType; private final NodeAndExplorerDataSourceImpl apiClient; - private final String _explorerUrl; public final static String defaultMainnetExplorerUrl = "https://api.ergoplatform.com"; public final static String defaultTestnetExplorerUrl = "https://api-testnet.ergoplatform.com"; @@ -34,24 +35,26 @@ public class RestApiErgoClient implements ErgoClient { * form `https://host[:port]` where port is optional. * If `null` or empty string passed then the Explorer client is not * initialized and the client works in the `node only` mode. - * @param proxy Requests are passed through this proxy (if non-null). + * @param httpClientBuilder Builder used to construct http client instances. If null, a new + * OkHttpClient with default parameters is used. */ - RestApiErgoClient(String nodeUrl, NetworkType networkType, String apiKey, String explorerUrl, @Nullable Proxy proxy) { - _nodeUrl = nodeUrl; + RestApiErgoClient(String nodeUrl, NetworkType networkType, String apiKey, String explorerUrl, @Nullable OkHttpClient.Builder httpClientBuilder) { _networkType = networkType; - ApiClient nodeClient = new ApiClient(_nodeUrl, "ApiKeyAuth", apiKey); - if (proxy != null) { - nodeClient.createDefaultAdapter(proxy); + + // if no httpClientBuilder is set, we use a single one for both api clients + if (httpClientBuilder == null) { + // just using the same builder is not enough - we have to derive the builder from an + // actual OkHttpClient instance to share the thread pools. + httpClientBuilder = new OkHttpClient().newBuilder(); } - _explorerUrl = explorerUrl; + + ApiClient nodeClient = new ApiClient(nodeUrl, "ApiKeyAuth", apiKey); + nodeClient.configureFromOkClientBuilder(httpClientBuilder); + ExplorerApiClient explorerClient; - if (!Strings.isNullOrEmpty(_explorerUrl)) { - if (proxy != null) { - explorerClient = new ExplorerApiClient(_explorerUrl, proxy); - } - else { - explorerClient = new ExplorerApiClient(_explorerUrl); - } + if (!Strings.isNullOrEmpty(explorerUrl)) { + explorerClient = new ExplorerApiClient(explorerUrl); + explorerClient.configureFromOkClientBuilder(httpClientBuilder); } else { explorerClient = null; } @@ -121,11 +124,12 @@ public static ErgoClient create(String nodeUrl, NetworkType networkType, String * `https://host:port/`. If null or empty, then explorer connection * is not initialized so that the resulting {@link ErgoClient} can * work in `node-only` mode. - * @param proxy Requests are passed through this proxy (if non-null). + * @param httpClientBuilder Builder used to construct http client instances. If null, a new + * OkHttpClient with default parameters is used. * @return a new instance of {@link ErgoClient} connected to a given node */ - public static ErgoClient createWithProxy(String nodeUrl, NetworkType networkType, String apiKey, String explorerUrl, @Nullable Proxy proxy) { - return new RestApiErgoClient(nodeUrl, networkType, apiKey, explorerUrl, proxy); + public static ErgoClient createWithHttpClientBuilder(String nodeUrl, NetworkType networkType, String apiKey, String explorerUrl, @Nullable OkHttpClient.Builder httpClientBuilder) { + return new RestApiErgoClient(nodeUrl, networkType, apiKey, explorerUrl, httpClientBuilder); } /** @@ -155,15 +159,16 @@ public static ErgoClient create(ErgoNodeConfig nodeConf, String explorerUrl) { * `https://host:port/`. If null or empty, then explorer connection * is not initialized so that the resulting {@link ErgoClient} can * work in `node-only` mode. - * @param proxy Requests are passed through this proxy (if non-null). + * @param httpClientBuilder Builder used to construct http client instances. If null, a new + * OkHttpClient with default parameters is used. */ - public static ErgoClient createWithProxy(ErgoNodeConfig nodeConf, String explorerUrl, @Nullable Proxy proxy) { - return RestApiErgoClient.createWithProxy( + public static ErgoClient createWithHttpClientBuilder(ErgoNodeConfig nodeConf, String explorerUrl, @Nullable OkHttpClient.Builder httpClientBuilder) { + return RestApiErgoClient.createWithHttpClientBuilder( nodeConf.getNodeApi().getApiUrl(), nodeConf.getNetworkType(), nodeConf.getNodeApi().getApiKey(), explorerUrl, - proxy + httpClientBuilder ); } diff --git a/java-client-generated/src/main/java/org/ergoplatform/explorer/client/ExplorerApiClient.java b/java-client-generated/src/main/java/org/ergoplatform/explorer/client/ExplorerApiClient.java index effacb4b..b43a37bd 100755 --- a/java-client-generated/src/main/java/org/ergoplatform/explorer/client/ExplorerApiClient.java +++ b/java-client-generated/src/main/java/org/ergoplatform/explorer/client/ExplorerApiClient.java @@ -2,16 +2,6 @@ import com.google.gson.Gson; import com.google.gson.JsonParseException; -import okhttp3.Interceptor; -import okhttp3.OkHttpClient; -import okhttp3.RequestBody; -import okhttp3.ResponseBody; -import retrofit2.Converter; -import retrofit2.Retrofit; -import retrofit2.converter.gson.GsonConverterFactory; -import retrofit2.converter.scalars.ScalarsConverterFactory; -import org.ergoplatform.explorer.client.auth.HttpBasicAuth; -import org.ergoplatform.explorer.client.auth.ApiKeyAuth; import java.io.IOException; import java.lang.annotation.Annotation; @@ -19,67 +9,33 @@ import java.net.Proxy; import java.text.DateFormat; import java.time.format.DateTimeFormatter; -import java.util.LinkedHashMap; -import java.util.Map; + +import okhttp3.OkHttpClient; +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import retrofit2.Converter; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; +import retrofit2.converter.scalars.ScalarsConverterFactory; public class ExplorerApiClient { private String _hostUrl; - private Map apiAuthorizations; private OkHttpClient.Builder okBuilder; private Retrofit.Builder adapterBuilder; private JSON json; private Proxy proxy; public ExplorerApiClient(String hostUrl) { - _hostUrl = hostUrl; - apiAuthorizations = new LinkedHashMap(); - createDefaultAdapter(); + this(hostUrl, null); } public ExplorerApiClient(String hostUrl, Proxy proxy) { _hostUrl = hostUrl; - apiAuthorizations = new LinkedHashMap(); this.proxy = proxy; createDefaultAdapter(); } - public ExplorerApiClient(String hostUrl, String[] authNames) { - this(hostUrl); - for(String authName : authNames) { - throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); - } - } - - /** - * Basic constructor for single auth name - * @param authName Authentication name - */ - public ExplorerApiClient(String hostUrl, String authName) { - this(hostUrl, new String[]{authName}); - } - - /** - * Helper constructor for single api key - * @param authName Authentication name - * @param apiKey API key - */ - public ExplorerApiClient(String hostUrl, String authName, String apiKey) { - this(hostUrl, authName); - this.setApiKey(apiKey); - } - - /** - * Helper constructor for single basic auth or password oauth2 - * @param authName Authentication name - * @param username Username - * @param password Password - */ - public ExplorerApiClient(String hostUrl, String authName, String username, String password) { - this(hostUrl, authName); - this.setCredentials(username, password); - } - public void createDefaultAdapter() { json = new JSON(); okBuilder = new OkHttpClient.Builder(); @@ -123,73 +79,6 @@ public ExplorerApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { return this; } - - /** - * Helper method to configure the first api key found - * @param apiKey API key - * @return ApiClient - */ - public ExplorerApiClient setApiKey(String apiKey) { - for(Interceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof ApiKeyAuth) { - ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; - keyAuth.setApiKey(apiKey); - return this; - } - } - return this; - } - - /** - * Helper method to configure the username/password for basic auth or password oauth - * @param username Username - * @param password Password - * @return ApiClient - */ - public ExplorerApiClient setCredentials(String username, String password) { - for(Interceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof HttpBasicAuth) { - HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; - basicAuth.setCredentials(username, password); - return this; - } - } - return this; - } - - /** - * Helper method to pre-set the oauth access token of the first oauth found in the apiAuthorizations (there should be only one) - * @param accessToken Access token - * @return ApiClient - */ - public ExplorerApiClient setAccessToken(String accessToken) { - return this; - } - - /** - * Adds an authorization to be used by the client - * @param authName Authentication name - * @param authorization Authorization interceptor - * @return ApiClient - */ - public ExplorerApiClient addAuthorization(String authName, Interceptor authorization) { - if (apiAuthorizations.containsKey(authName)) { - throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); - } - apiAuthorizations.put(authName, authorization); - okBuilder.addInterceptor(authorization); - return this; - } - - public Map getApiAuthorizations() { - return apiAuthorizations; - } - - public ExplorerApiClient setApiAuthorizations(Map apiAuthorizations) { - this.apiAuthorizations = apiAuthorizations; - return this; - } - public Retrofit.Builder getAdapterBuilder() { return adapterBuilder; } @@ -203,20 +92,21 @@ public OkHttpClient.Builder getOkBuilder() { return okBuilder; } - public void addAuthsToOkBuilder(OkHttpClient.Builder okBuilder) { - for(Interceptor apiAuthorization : apiAuthorizations.values()) { - okBuilder.addInterceptor(apiAuthorization); - } - } - /** * Clones the okBuilder given in parameter, adds the auth interceptors and uses it to configure the Retrofit * @param okClient An instance of OK HTTP client */ public void configureFromOkclient(OkHttpClient okClient) { this.okBuilder = okClient.newBuilder(); - addAuthsToOkBuilder(this.okBuilder); } + + /** + * Uses the okBuilder given in parameter, adds the auth interceptors and uses it to configure the Retrofit + * @param okClientBuilder An instance of OK HTTP client builder + */ + public void configureFromOkClientBuilder(OkHttpClient.Builder okClientBuilder) { + this.okBuilder = okClientBuilder; + } } /** diff --git a/java-client-generated/src/main/java/org/ergoplatform/restapi/client/ApiClient.java b/java-client-generated/src/main/java/org/ergoplatform/restapi/client/ApiClient.java index 9135f9f5..22014f0a 100755 --- a/java-client-generated/src/main/java/org/ergoplatform/restapi/client/ApiClient.java +++ b/java-client-generated/src/main/java/org/ergoplatform/restapi/client/ApiClient.java @@ -2,7 +2,7 @@ import com.google.gson.Gson; import com.google.gson.JsonParseException; -import com.google.gson.JsonElement; + import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.RequestBody; @@ -21,8 +21,6 @@ import java.text.DateFormat; import java.util.LinkedHashMap; import java.util.Map; -import java.util.HashMap; -import java.net.Proxy; public class ApiClient { @@ -109,24 +107,6 @@ public void createDefaultAdapter() { .addConverterFactory(GsonCustomConverterFactory.create(json.getGson())); } - public void createDefaultAdapter(Proxy proxy) { - json = new JSON(); - okBuilder = new OkHttpClient.Builder(); - - if (proxy != null) { - okBuilder.proxy(proxy); - } - - if (!_hostUrl.endsWith("/")) - _hostUrl = _hostUrl + "/"; - - adapterBuilder = new Retrofit - .Builder() - .baseUrl(_hostUrl) - .addConverterFactory(ScalarsConverterFactory.create()) - .addConverterFactory(GsonCustomConverterFactory.create(json.getGson())); - } - public S createService(Class serviceClass) { return adapterBuilder .client(okBuilder.build()) @@ -245,9 +225,17 @@ public void addAuthsToOkBuilder(OkHttpClient.Builder okBuilder) { * @param okClient An instance of OK HTTP client */ public void configureFromOkclient(OkHttpClient okClient) { - this.okBuilder = okClient.newBuilder(); - addAuthsToOkBuilder(this.okBuilder); + configureFromOkClientBuilder(okClient.newBuilder()); } + + /** + * Uses the okBuilder given in parameter, adds the auth interceptors and uses it to configure the Retrofit + * @param okClientBuilder An instance of OK HTTP client builder + */ + public void configureFromOkClientBuilder(OkHttpClient.Builder okClientBuilder) { + this.okBuilder = okClientBuilder; + addAuthsToOkBuilder(this.okBuilder); + } } /** diff --git a/lib-impl/src/main/java/org/ergoplatform/appkit/impl/NodeAndExplorerDataSourceImpl.java b/lib-impl/src/main/java/org/ergoplatform/appkit/impl/NodeAndExplorerDataSourceImpl.java index ee34d989..f90f4f36 100644 --- a/lib-impl/src/main/java/org/ergoplatform/appkit/impl/NodeAndExplorerDataSourceImpl.java +++ b/lib-impl/src/main/java/org/ergoplatform/appkit/impl/NodeAndExplorerDataSourceImpl.java @@ -59,9 +59,9 @@ public class NodeAndExplorerDataSourceImpl implements BlockchainDataSource { public NodeAndExplorerDataSourceImpl(ApiClient nodeClient, @Nullable ExplorerApiClient explorerClient) { - OkHttpClient _ok = nodeClient.getOkBuilder().build(); + OkHttpClient ok = nodeClient.getOkBuilder().build(); Retrofit nodeRetrofit = nodeClient.getAdapterBuilder() - .client(_ok) + .client(ok) .build(); nodeInfoApi = nodeRetrofit.create(InfoApi.class); @@ -72,10 +72,10 @@ public NodeAndExplorerDataSourceImpl(ApiClient nodeClient, @Nullable ExplorerApi if (explorerClient != null) { OkHttpClient okExplorer = explorerClient.getOkBuilder().build(); - Retrofit _retrofitExplorer = explorerClient.getAdapterBuilder() + Retrofit retrofitExplorer = explorerClient.getAdapterBuilder() .client(okExplorer) .build(); - explorerApi = _retrofitExplorer.create(DefaultApi.class); + explorerApi = retrofitExplorer.create(DefaultApi.class); } else explorerApi = null;