From 2bc5767fbf5f3ce53db54d02b8e3376043a528e5 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 24 Jun 2025 13:06:12 -0700 Subject: [PATCH 01/30] Updated SplitClientConfig --- .../io/split/client/SplitClientConfig.java | 73 +++++++++++++++- .../io/split/client/dtos/ProxyMTLSAuth.java | 41 +++++++++ .../split/client/SplitClientConfigTest.java | 83 +++++++++++++++++++ 3 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index fd312c3b..f521cd33 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -1,5 +1,6 @@ package io.split.client; +import io.split.client.dtos.ProxyMTLSAuth; import io.split.client.impressions.ImpressionListener; import io.split.client.impressions.ImpressionsManager; import io.split.client.utils.FileTypeEnum; @@ -85,6 +86,8 @@ public class SplitClientConfig { private final HttpHost _proxy; private final String _proxyUsername; private final String _proxyPassword; + private final String _proxyToken; + private final ProxyMTLSAuth _proxyMtlsAuth; // To be set during startup public static String splitSdkVersion; @@ -118,6 +121,8 @@ private SplitClientConfig(String endpoint, HttpHost proxy, String proxyUsername, String proxyPassword, + String proxyToken, + ProxyMTLSAuth proxyMtlsAuth, int eventsQueueSize, long eventSendIntervalInMillis, int maxStringLength, @@ -171,6 +176,8 @@ private SplitClientConfig(String endpoint, _proxy = proxy; _proxyUsername = proxyUsername; _proxyPassword = proxyPassword; + _proxyToken = proxyToken; + _proxyMtlsAuth = proxyMtlsAuth; _eventsQueueSize = eventsQueueSize; _eventSendIntervalInMillis = eventSendIntervalInMillis; _maxStringLength = maxStringLength; @@ -302,6 +309,14 @@ public String proxyPassword() { return _proxyPassword; } + public String proxyToken() { + return _proxyToken; + } + + public ProxyMTLSAuth proxyMTLSAuth() { + return _proxyMtlsAuth; + } + public long eventSendIntervalInMillis() { return _eventSendIntervalInMillis; } @@ -417,8 +432,8 @@ public boolean isSdkEndpointOverridden() { } public CustomHttpModule alternativeHTTPModule() { return _alternativeHTTPModule; } - public static final class Builder { + public static final class Builder { private String _endpoint = SDK_ENDPOINT; private boolean _endpointSet = false; private String _eventsEndpoint = EVENTS_ENDPOINT; @@ -442,6 +457,8 @@ public static final class Builder { private int _proxyPort = -1; private String _proxyUsername; private String _proxyPassword; + private String _proxyToken; + private ProxyMTLSAuth _proxyMtlsAuth; private int _eventsQueueSize = 500; private long _eventSendIntervalInMillis = 30 * (long)1000; private int _maxStringLength = 250; @@ -776,6 +793,28 @@ public Builder proxyPassword(String proxyPassword) { return this; } + /** + * Set the token for authentication against the proxy (if proxy settings are enabled). (Optional). + * + * @param proxyToken + * @return this builder + */ + public Builder proxyToken(String proxyToken) { + _proxyToken = proxyToken; + return this; + } + + /** + * Set the mtls authentication against the proxy (if proxy settings are enabled). (Optional). + * + * @param proxyMtlsAuth + * @return this builder + */ + public Builder proxyMtlsAuth(ProxyMTLSAuth proxyMtlsAuth) { + _proxyMtlsAuth = proxyMtlsAuth; + return this; + } + /** * Disables running destroy() on shutdown by default. * @@ -1096,6 +1135,34 @@ private void verifyAlternativeClient() { } } + private void verifyProxy() { + if (_proxyPort == -1) { + return; + } + + if (_proxyUsername == null && _proxyToken == null && _proxyMtlsAuth == null) { + return; + } + + if (_proxyUsername != null && _proxyToken != null) { + throw new IllegalArgumentException("Proxy user and Proxy token params are updated, set only one param."); + } + + if (_proxyUsername != null && _proxyMtlsAuth != null) { + throw new IllegalArgumentException("Proxy user and Proxy mTLS params are updated, set only one param."); + } + + if (_proxyToken != null && _proxyMtlsAuth != null) { + throw new IllegalArgumentException("Proxy token and Proxy mTLS params are updated, set only one param."); + } + + if (_proxyMtlsAuth != null) { + if (_proxyMtlsAuth.getP12File() == null || _proxyMtlsAuth.getP12FilePassKey() == null) { + throw new IllegalArgumentException("Proxy mTLS must have p12 file path and name, and pass phrase."); + } + } + } + public SplitClientConfig build() { verifyRates(); @@ -1108,6 +1175,8 @@ public SplitClientConfig build() { verifyAlternativeClient(); + verifyProxy(); + if (_numThreadsForSegmentFetch <= 0) { throw new IllegalArgumentException("Number of threads for fetching segments MUST be greater than zero"); } @@ -1133,6 +1202,8 @@ public SplitClientConfig build() { proxy(), _proxyUsername, _proxyPassword, + _proxyToken, + _proxyMtlsAuth, _eventsQueueSize, _eventSendIntervalInMillis, _maxStringLength, diff --git a/client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java b/client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java new file mode 100644 index 00000000..ddd59696 --- /dev/null +++ b/client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java @@ -0,0 +1,41 @@ +package io.split.client.dtos; + +public class ProxyMTLSAuth { + private final String _proxyP12File; + private final String _proxyP12FilePassKey; + + private ProxyMTLSAuth(String proxyP12File, String proxyP12FilePassKey) { + _proxyP12File = proxyP12File; + _proxyP12FilePassKey = proxyP12FilePassKey; + } + + public String getP12File() { return _proxyP12File; } + + public String getP12FilePassKey() { return _proxyP12FilePassKey; } + + public static ProxyMTLSAuth.Builder builder() { + return new ProxyMTLSAuth.Builder(); + } + + public static class Builder { + private String _p12File; + private String _p12FilePassKey; + + public Builder() { + } + + public ProxyMTLSAuth.Builder proxyP12File(String p12File) { + _p12File = p12File; + return this; + } + + public ProxyMTLSAuth.Builder proxyP12FilePassKey(String p12FilePassKey) { + _p12FilePassKey = p12FilePassKey; + return this; + } + + public ProxyMTLSAuth build() { + return new ProxyMTLSAuth(_p12File, _p12FilePassKey); + } + } +} \ No newline at end of file diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index 1b640071..9e9688e1 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -1,6 +1,7 @@ package io.split.client; import com.google.common.util.concurrent.ThreadFactoryBuilder; +import io.split.client.dtos.ProxyMTLSAuth; import io.split.client.impressions.Impression; import io.split.client.impressions.ImpressionListener; import io.split.client.impressions.ImpressionsManager; @@ -252,6 +253,88 @@ public Map> getHeaderOverrides(RequestContext context) { SplitClientConfig config2 = SplitClientConfig.builder().build(); Assert.assertNull(config2.customHeaderDecorator()); + } + + @Test + public void checkProxyParams() { + SplitClientConfig config = SplitClientConfig.builder() + .proxyHost("proxy-host") + .proxyPort(8888).build(); + Assert.assertEquals("proxy-host", config.proxy().getHostName()); + Assert.assertEquals(8888, config.proxy().getPort()); + + config = SplitClientConfig.builder() + .proxyHost("proxy-host") + .proxyPort(8888) + .proxyUsername("user") + .proxyPassword("pass") + .build(); + Assert.assertEquals("user", config.proxyUsername()); + Assert.assertEquals("pass", config.proxyPassword()); + config = SplitClientConfig.builder() + .proxyHost("proxy-host") + .proxyPort(8888) + .proxyToken("my-token") + .build(); + Assert.assertEquals("my-token", config.proxyToken()); + + config = SplitClientConfig.builder() + .proxyHost("proxy-host") + .proxyPort(8888) + .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build()) + .build(); + Assert.assertEquals("path/to/file", config.proxyMTLSAuth().getP12File()); + Assert.assertEquals("pass-key", config.proxyMTLSAuth().getP12FilePassKey()); + } + + @Test(expected = IllegalArgumentException.class) + public void cannotUseProxyTokenAndProxyUsername() { + SplitClientConfig.builder() + .proxyHost("proxy-host") + .proxyPort(8888) + .proxyUsername("user") + .proxyPassword("pass") + .proxyToken("my-token") + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void cannotUseProxyUserAndProxyMtls() { + SplitClientConfig.builder() + .proxyHost("proxy-host") + .proxyPort(8888) + .proxyUsername("user") + .proxyPassword("pass") + .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build()) + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void cannotUseProxyTokenAndProxyMtls() { + SplitClientConfig.builder() + .proxyHost("proxy-host") + .proxyPort(8888) + .proxyToken("my-token") + .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build()) + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void mustUseP12FileWithProxyMtls() { + SplitClientConfig.builder() + .proxyHost("proxy-host") + .proxyPort(8888) + .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12FilePassKey("pass-key").build()) + .build(); + } + + @Test(expected = IllegalArgumentException.class) + public void mustUseP12PassKeyWithProxyMtls() { + SplitClientConfig.builder() + .proxyHost("proxy-host") + .proxyPort(8888) + .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").build()) + .build(); } } \ No newline at end of file From 3cca5ea15dbb7185128a54091a72e9cb614b92d3 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 24 Jun 2025 21:37:37 -0700 Subject: [PATCH 02/30] Added proxy scheme --- .../io/split/client/SplitClientConfig.java | 23 ++++++++++++++++++- .../split/client/SplitClientConfigTest.java | 10 ++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index f521cd33..6c388b2d 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -35,6 +35,11 @@ public class SplitClientConfig { public static final String STREAMING_ENDPOINT = "https://streaming.split.io/sse"; public static final String TELEMETRY_ENDPOINT = "https://telemetry.split.io/api/v1"; + public static class HttpScheme { + public static final String HTTP = "http"; + public static final String HTTPS = "https"; + } + private final String _endpoint; private final String _eventsEndpoint; @@ -455,6 +460,7 @@ public static final class Builder { private int _waitBeforeShutdown = 5000; private String _proxyHost = "localhost"; private int _proxyPort = -1; + private String _proxyScheme = HttpScheme.HTTP; private String _proxyUsername; private String _proxyPassword; private String _proxyToken; @@ -771,6 +777,17 @@ public Builder proxyPort(int proxyPort) { return this; } + /** + * The http scheme of the proxy. Default is http. + * + * @param proxyScheme protocol for the proxy + * @return this builder + */ + public Builder proxyScheme(String proxyScheme) { + _proxyScheme = proxyScheme; + return this; + } + /** * Set the username for authentication against the proxy (if proxy settings are enabled). (Optional). * @@ -827,7 +844,7 @@ public Builder disableDestroyOnShutDown() { HttpHost proxy() { if (_proxyPort != -1) { - return new HttpHost(_proxyHost, _proxyPort); + return new HttpHost(_proxyScheme, _proxyHost, _proxyPort); } // Default is no proxy. return null; @@ -1140,6 +1157,10 @@ private void verifyProxy() { return; } + if (!(_proxyScheme.equals(HttpScheme.HTTP) || _proxyScheme.equals(HttpScheme.HTTPS))) { + throw new IllegalArgumentException("Proxy scheme must be either http or https."); + } + if (_proxyUsername == null && _proxyToken == null && _proxyMtlsAuth == null) { return; } diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index 9e9688e1..ebb4803b 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -266,6 +266,7 @@ public void checkProxyParams() { config = SplitClientConfig.builder() .proxyHost("proxy-host") .proxyPort(8888) + .proxyScheme(SplitClientConfig.HttpScheme.HTTPS) .proxyUsername("user") .proxyPassword("pass") .build(); @@ -288,6 +289,15 @@ public void checkProxyParams() { Assert.assertEquals("pass-key", config.proxyMTLSAuth().getP12FilePassKey()); } + @Test(expected = IllegalArgumentException.class) + public void cannotUseInvalidHttpScheme() { + SplitClientConfig.builder() + .proxyHost("proxy-host") + .proxyPort(8888) + .proxyScheme("ftp") + .build(); + } + @Test(expected = IllegalArgumentException.class) public void cannotUseProxyTokenAndProxyUsername() { SplitClientConfig.builder() From 0267513dcada5a743cacf2d78814bae7a3dce8cb Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Wed, 25 Jun 2025 10:40:06 -0700 Subject: [PATCH 03/30] Update factory --- .../io/split/client/SplitFactoryImpl.java | 35 +++++++++++++++- .../io/split/client/SplitFactoryImplTest.java | 40 ++++++++++++++++++- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 9932cbf8..978f1603 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -92,6 +92,7 @@ import io.split.telemetry.synchronizer.TelemetrySynchronizer; import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.BearerToken; import org.apache.hc.client5.http.auth.Credentials; import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; import org.apache.hc.client5.http.config.RequestConfig; @@ -113,11 +114,14 @@ import org.slf4j.LoggerFactory; import pluggable.CustomStorageWrapper; +import javax.net.ssl.SSLContext; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; +import java.nio.file.Paths; +import java.security.KeyStore; import java.util.concurrent.ExecutorService; import java.util.stream.Collectors; import java.util.HashSet; @@ -518,8 +522,28 @@ public boolean isDestroyed() { protected static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata, RequestDecorator requestDecorator) throws URISyntaxException { + + SSLContext sslContext; + if (config.proxyMTLSAuth() != null) { + _log.debug("Proxy setup using mTLS"); + try { + KeyStore keyStore = KeyStore.getInstance("PKCS12"); + InputStream keystoreStream = java.nio.file.Files.newInputStream(Paths.get(config.proxyMTLSAuth().getP12File())); + keyStore.load(keystoreStream, config.proxyMTLSAuth().getP12FilePassKey().toCharArray()); + sslContext = SSLContexts.custom() + .loadKeyMaterial(keyStore, config.proxyMTLSAuth().getP12FilePassKey().toCharArray()) + .build(); + } catch (Exception e) { + _log.error("Exception caught while processing p12 file for Proxy mTLS auth: ", e); + _log.warn("Ignoring p12 mTLS config and switching to default context"); + sslContext = SSLContexts.createSystemDefault(); + } + } else { + sslContext = SSLContexts.createSystemDefault(); + } + SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create() - .setSslContext(SSLContexts.createSystemDefault()) + .setSslContext(sslContext) .setTlsVersions(TLS.V_1_1, TLS.V_1_2) .build(); @@ -604,6 +628,15 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, httpClientbuilder.setDefaultCredentialsProvider(credsProvider); } + if (config.proxyToken() != null) { + _log.debug("Proxy setup using token"); + BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); + AuthScope siteScope = new AuthScope(config.proxy().getHostName(), config.proxy().getPort()); + Credentials siteCreds = new BearerToken(config.proxyToken()); + credsProvider.setCredentials(siteScope, siteCreds); + httpClientbuilder.setDefaultCredentialsProvider(credsProvider); + } + return httpClientbuilder; } diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index a6da1069..2a691a4f 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -1,5 +1,6 @@ package io.split.client; +import io.split.client.dtos.ProxyMTLSAuth; import io.split.client.impressions.ImpressionsManager; import io.split.client.utils.FileTypeEnum; import io.split.integrations.IntegrationsConfig; @@ -10,7 +11,6 @@ import junit.framework.TestCase; import org.awaitility.Awaitility; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; import static org.mockito.Mockito.when; @@ -102,9 +102,45 @@ public void testFactoryInstantiationWithProxy() throws Exception { .proxyHost(ENDPOINT) .build(); SplitFactoryImpl splitFactory = new SplitFactoryImpl(API_KEY, splitClientConfig); - assertNotNull(splitFactory.client()); assertNotNull(splitFactory.manager()); + + splitClientConfig = SplitClientConfig.builder() + .enableDebug() + .impressionsMode(ImpressionsManager.Mode.DEBUG) + .impressionsRefreshRate(1) + .endpoint(ENDPOINT,EVENTS_ENDPOINT) + .telemetryURL(SplitClientConfig.TELEMETRY_ENDPOINT) + .authServiceURL(AUTH_SERVICE) + .setBlockUntilReadyTimeout(1000) + .proxyPort(6060) + .proxyToken("12345") + .proxyHost(ENDPOINT) + .build(); + SplitFactoryImpl splitFactory2 = new SplitFactoryImpl(API_KEY, splitClientConfig); + assertNotNull(splitFactory2.client()); + assertNotNull(splitFactory2.manager()); + + splitClientConfig = SplitClientConfig.builder() + .enableDebug() + .impressionsMode(ImpressionsManager.Mode.DEBUG) + .impressionsRefreshRate(1) + .endpoint(ENDPOINT,EVENTS_ENDPOINT) + .telemetryURL(SplitClientConfig.TELEMETRY_ENDPOINT) + .authServiceURL(AUTH_SERVICE) + .setBlockUntilReadyTimeout(1000) + .proxyPort(6060) + .proxyScheme("https") + .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("file").proxyP12FilePassKey("pass").build()) + .proxyHost(ENDPOINT) + .build(); + SplitFactoryImpl splitFactory3 = new SplitFactoryImpl(API_KEY, splitClientConfig); + assertNotNull(splitFactory3.client()); + assertNotNull(splitFactory3.manager()); + + splitFactory.destroy(); + splitFactory2.destroy(); + splitFactory3.destroy(); } @Test From 436dc2aec2a6cae6a2fe488c3b00d36410d93f08 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Wed, 25 Jun 2025 16:01:51 -0700 Subject: [PATCH 04/30] Added proxy tests --- .../io/split/client/SplitFactoryImplTest.java | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index 2a691a4f..c99c2ff0 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -4,11 +4,21 @@ import io.split.client.impressions.ImpressionsManager; import io.split.client.utils.FileTypeEnum; import io.split.integrations.IntegrationsConfig; +import io.split.service.SplitHttpClientImpl; import io.split.storages.enums.OperationMode; import io.split.storages.pluggable.domain.UserStorageWrapper; import io.split.telemetry.storage.TelemetryStorage; import io.split.telemetry.synchronizer.TelemetrySynchronizer; import junit.framework.TestCase; +import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.BearerToken; +import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; +import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.classic.MinimalHttpClient; +import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner; +import org.apache.hc.core5.http.HttpHost; import org.awaitility.Awaitility; import org.junit.Assert; import org.junit.Test; @@ -24,6 +34,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URISyntaxException; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -105,6 +116,37 @@ public void testFactoryInstantiationWithProxy() throws Exception { assertNotNull(splitFactory.client()); assertNotNull(splitFactory.manager()); + Field splitHttpClientField = SplitFactoryImpl.class.getDeclaredField("_splitHttpClient"); + splitHttpClientField.setAccessible(true); + SplitHttpClientImpl client = (SplitHttpClientImpl) splitHttpClientField.get(splitFactory); + + Field httpClientField = SplitHttpClientImpl.class.getDeclaredField("_client"); + httpClientField.setAccessible(true); + Class InternalHttp = Class.forName("org.apache.hc.client5.http.impl.classic.InternalHttpClient"); + + Field routePlannerField = InternalHttp.getDeclaredField("routePlanner"); + routePlannerField.setAccessible(true); + DefaultProxyRoutePlanner routePlanner = (DefaultProxyRoutePlanner) routePlannerField.get(InternalHttp.cast(httpClientField.get(client))); + + Field proxyField = DefaultProxyRoutePlanner.class.getDeclaredField("proxy"); + proxyField.setAccessible(true); + HttpHost proxy = (HttpHost) proxyField.get(routePlanner); + + Assert.assertEquals("http", proxy.getSchemeName()); + Assert.assertEquals(ENDPOINT, proxy.getHostName()); + Assert.assertEquals(6060, proxy.getPort()); + + Field credentialsProviderField = InternalHttp.getDeclaredField("credentialsProvider"); + credentialsProviderField.setAccessible(true); + BasicCredentialsProvider credentialsProvider = (BasicCredentialsProvider) credentialsProviderField.get(InternalHttp.cast(httpClientField.get(client))); + + Field credMapField = BasicCredentialsProvider.class.getDeclaredField("credMap"); + credMapField.setAccessible(true); + ConcurrentHashMap credMap = (ConcurrentHashMap) credMapField.get(credentialsProvider); + + Assert.assertEquals("test", credMap.entrySet().stream().iterator().next().getValue().getUserName()); + assertNotNull(credMap.entrySet().stream().iterator().next().getValue().getUserPassword()); + splitClientConfig = SplitClientConfig.builder() .enableDebug() .impressionsMode(ImpressionsManager.Mode.DEBUG) @@ -114,13 +156,31 @@ public void testFactoryInstantiationWithProxy() throws Exception { .authServiceURL(AUTH_SERVICE) .setBlockUntilReadyTimeout(1000) .proxyPort(6060) - .proxyToken("12345") + .proxyToken("123456789") .proxyHost(ENDPOINT) .build(); SplitFactoryImpl splitFactory2 = new SplitFactoryImpl(API_KEY, splitClientConfig); assertNotNull(splitFactory2.client()); assertNotNull(splitFactory2.manager()); + Field splitHttpClientField2 = SplitFactoryImpl.class.getDeclaredField("_splitHttpClient"); + splitHttpClientField2.setAccessible(true); + SplitHttpClientImpl client2 = (SplitHttpClientImpl) splitHttpClientField2.get(splitFactory2); + + Field httpClientField2 = SplitHttpClientImpl.class.getDeclaredField("_client"); + httpClientField2.setAccessible(true); + Class InternalHttp2 = Class.forName("org.apache.hc.client5.http.impl.classic.InternalHttpClient"); + + Field credentialsProviderField2 = InternalHttp.getDeclaredField("credentialsProvider"); + credentialsProviderField2.setAccessible(true); + BasicCredentialsProvider credentialsProvider2 = (BasicCredentialsProvider) credentialsProviderField2.get(InternalHttp2.cast(httpClientField2.get(client2))); + + Field credMapField2 = BasicCredentialsProvider.class.getDeclaredField("credMap"); + credMapField2.setAccessible(true); + ConcurrentHashMap credMap2 = (ConcurrentHashMap) credMapField2.get(credentialsProvider2); + + Assert.assertEquals("123456789", credMap2.entrySet().stream().iterator().next().getValue().getToken()); + splitClientConfig = SplitClientConfig.builder() .enableDebug() .impressionsMode(ImpressionsManager.Mode.DEBUG) From b42fddc0e37fe47a50f2c4dbb2cc84fbe836f63b Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Thu, 26 Jun 2025 12:48:39 -0700 Subject: [PATCH 05/30] updated test --- .../io/split/client/SplitFactoryImplTest.java | 81 +++++++++++++++--- client/src/test/resources/keyStore.p12 | Bin 0 -> 3011 bytes 2 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 client/src/test/resources/keyStore.p12 diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index c99c2ff0..4597b615 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -14,11 +14,11 @@ import org.apache.hc.client5.http.auth.BearerToken; import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; -import org.apache.hc.client5.http.impl.classic.MinimalHttpClient; +import org.apache.hc.client5.http.impl.io.DefaultHttpClientConnectionOperator; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner; import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.config.Registry; import org.awaitility.Awaitility; import org.junit.Assert; import org.junit.Test; @@ -34,6 +34,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URISyntaxException; +import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -98,12 +99,12 @@ public void testFactoryInstantiationIntegrationsConfig() throws Exception { } @Test - public void testFactoryInstantiationWithProxy() throws Exception { + public void testFactoryInstantiationWithProxyCredentials() throws Exception { SplitClientConfig splitClientConfig = SplitClientConfig.builder() .enableDebug() .impressionsMode(ImpressionsManager.Mode.DEBUG) .impressionsRefreshRate(1) - .endpoint(ENDPOINT,EVENTS_ENDPOINT) + .endpoint(ENDPOINT, EVENTS_ENDPOINT) .telemetryURL(SplitClientConfig.TELEMETRY_ENDPOINT) .authServiceURL(AUTH_SERVICE) .setBlockUntilReadyTimeout(1000) @@ -147,11 +148,16 @@ public void testFactoryInstantiationWithProxy() throws Exception { Assert.assertEquals("test", credMap.entrySet().stream().iterator().next().getValue().getUserName()); assertNotNull(credMap.entrySet().stream().iterator().next().getValue().getUserPassword()); - splitClientConfig = SplitClientConfig.builder() + splitFactory.destroy(); + } + + @Test + public void testFactoryInstantiationWithProxyToken() throws Exception { + SplitClientConfig splitClientConfig = SplitClientConfig.builder() .enableDebug() .impressionsMode(ImpressionsManager.Mode.DEBUG) .impressionsRefreshRate(1) - .endpoint(ENDPOINT,EVENTS_ENDPOINT) + .endpoint(ENDPOINT, EVENTS_ENDPOINT) .telemetryURL(SplitClientConfig.TELEMETRY_ENDPOINT) .authServiceURL(AUTH_SERVICE) .setBlockUntilReadyTimeout(1000) @@ -171,7 +177,7 @@ public void testFactoryInstantiationWithProxy() throws Exception { httpClientField2.setAccessible(true); Class InternalHttp2 = Class.forName("org.apache.hc.client5.http.impl.classic.InternalHttpClient"); - Field credentialsProviderField2 = InternalHttp.getDeclaredField("credentialsProvider"); + Field credentialsProviderField2 = InternalHttp2.getDeclaredField("credentialsProvider"); credentialsProviderField2.setAccessible(true); BasicCredentialsProvider credentialsProvider2 = (BasicCredentialsProvider) credentialsProviderField2.get(InternalHttp2.cast(httpClientField2.get(client2))); @@ -181,7 +187,12 @@ public void testFactoryInstantiationWithProxy() throws Exception { Assert.assertEquals("123456789", credMap2.entrySet().stream().iterator().next().getValue().getToken()); - splitClientConfig = SplitClientConfig.builder() + splitFactory2.destroy(); + } + + @Test + public void testFactoryInstantiationWithProxyMtls() throws Exception { + SplitClientConfig splitClientConfig = SplitClientConfig.builder() .enableDebug() .impressionsMode(ImpressionsManager.Mode.DEBUG) .impressionsRefreshRate(1) @@ -191,15 +202,61 @@ public void testFactoryInstantiationWithProxy() throws Exception { .setBlockUntilReadyTimeout(1000) .proxyPort(6060) .proxyScheme("https") - .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("file").proxyP12FilePassKey("pass").build()) + .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("src/test/resources/keyStore.p12").proxyP12FilePassKey("split").build()) .proxyHost(ENDPOINT) .build(); SplitFactoryImpl splitFactory3 = new SplitFactoryImpl(API_KEY, splitClientConfig); assertNotNull(splitFactory3.client()); assertNotNull(splitFactory3.manager()); - splitFactory.destroy(); - splitFactory2.destroy(); + Field splitHttpClientField3 = SplitFactoryImpl.class.getDeclaredField("_splitHttpClient"); + splitHttpClientField3.setAccessible(true); + SplitHttpClientImpl client3 = (SplitHttpClientImpl) splitHttpClientField3.get(splitFactory3); + + Field httpClientField3 = SplitHttpClientImpl.class.getDeclaredField("_client"); + httpClientField3.setAccessible(true); + Class InternalHttp3 = Class.forName("org.apache.hc.client5.http.impl.classic.InternalHttpClient"); + + Field connManagerField = InternalHttp3.getDeclaredField("connManager"); + connManagerField.setAccessible(true); + PoolingHttpClientConnectionManager connManager = (PoolingHttpClientConnectionManager) connManagerField.get(InternalHttp3.cast(httpClientField3.get(client3))); + + Field connectionOperatorField = PoolingHttpClientConnectionManager.class.getDeclaredField("connectionOperator"); + connectionOperatorField.setAccessible(true); + DefaultHttpClientConnectionOperator connectionOperator = (DefaultHttpClientConnectionOperator) connectionOperatorField.get(connManager); + + Field tlsSocketStrategyLookupField = DefaultHttpClientConnectionOperator.class.getDeclaredField("tlsSocketStrategyLookup"); + tlsSocketStrategyLookupField.setAccessible(true); + Registry tlsSocketStrategyLookup = (Registry) tlsSocketStrategyLookupField.get(connectionOperator); + + Field mapField = Registry.class.getDeclaredField("map"); + mapField.setAccessible(true); + Class map = mapField.get(tlsSocketStrategyLookup).getClass(); + + Class value = ((ConcurrentHashMap) map.cast(mapField.get(tlsSocketStrategyLookup))).get("https").getClass(); + + Field arg1Field = value.getDeclaredField("arg$1"); + arg1Field.setAccessible(true); + Class sslConnectionSocketFactory = arg1Field.get(((ConcurrentHashMap) map.cast(mapField.get(tlsSocketStrategyLookup))).get("https")).getClass(); + + Field socketFactoryField = sslConnectionSocketFactory.getDeclaredField("socketFactory"); + socketFactoryField.setAccessible(true); + Class socketFactory = socketFactoryField.get(arg1Field.get(((ConcurrentHashMap) map.cast(mapField.get(tlsSocketStrategyLookup))).get("https"))).getClass(); + + Field contextField = socketFactory.getDeclaredField("context"); + contextField.setAccessible(true); + Class context = Class.forName("sun.security.ssl.SSLContextImpl"); + + Field keyManagerField = context.getDeclaredField("keyManager"); + keyManagerField.setAccessible(true); + Class keyManager = keyManagerField.get(contextField.get(socketFactoryField.get(arg1Field.get(((ConcurrentHashMap) map.cast(mapField.get(tlsSocketStrategyLookup))).get("https"))))).getClass(); + + Field credentialsMapField = keyManager.getDeclaredField("credentialsMap"); + credentialsMapField.setAccessible(true); + HashMap credentialsMap = (HashMap) credentialsMapField.get(keyManagerField.get(contextField.get(socketFactoryField.get(arg1Field.get(((ConcurrentHashMap) map.cast(mapField.get(tlsSocketStrategyLookup))).get("https")))))); + + assertNotNull(credentialsMap.get("1")); + splitFactory3.destroy(); } diff --git a/client/src/test/resources/keyStore.p12 b/client/src/test/resources/keyStore.p12 new file mode 100644 index 0000000000000000000000000000000000000000..ce2b34171195aa55cb4640301caff60021c29543 GIT binary patch literal 3011 zcmai$XE+-Q7srLfiVkefQoQc-zR$fM-w)?G&-wj7oNvE#U|4V)DS!-y1qYH-iN)&2p3nj)0C`xj8xRY2 zxyFt#ENJH6h&&Gq>c2)kqyUoZ*8Xn-fI0m$fM{W6FsXk>8kisuLdY$m_vbJ2>$zO| zl_j;C@WK|fr!>V*E6Tg-pV4aCIT>Xf8RIG|MAKc zq7JM#CtS`-CKsFIE4~mg2x>y@v{hXPJdkJIa=^x#4b*T!B?MVcHRClaQBId^JVP$8- zb;}*$A_nmkGCevGVq5>|v*)E}vO||q(p5M;_!Cu_i`Ji)kyD`=;!FI7> z-0VSnOwAVPWt+%ve%2BT98->zPm-fcb6kfTetjK(xyrjq^kuoRtEln}qI+5;4puY7 zUT&H-JhO6T3z;0x591ST9X2pD;sV~7KX}zRV}t>~tW|r+yte~em24=KL{snEDYrhn z3c&a6Q{KbQDOe^&sDyoPrZyG*tsF-F&T)J_L{W2B>RHm%)2#wx-D;Y}CR!`#F@b5K zC?MAKFJ>^jhC%;cL2@tm6$Zdde;aF3;dCa2m-+hLB?VQnss~DhPfSsG4t4RTK4n2M zV1vLEZ{9aQ>KSIRAeNLSpeIzdh96e8q0$9J#NH8PHE4)wnB&-)Tyo|`bad5oK93X@ zhZP4lwN>vFjeMO8b^P>ELdJjzQ<(vL&fiR}(UHxvrEp}!T-wb(AA4Wvn3AVzo zBKWrXUNC1niMLIuNkI!RBcsu8b&F*l&E<$07M4+nc4Tef{(6O;mM(`p)wtnF3lC9% ztB}ji4KI|Sq+Gj*#AZy}GZzWb=pX}$rP&ycd{v<_;!(GaR@ibDpp2RlQQNs+ z8P7&2ahiSFw0o|W6}IszL~<7O&==%fW0M(5sxEQ6wroWD5&GCFfOEk1cTqdNYm#@; z+PN0y@m(FjH@{Mme1^cC15RQL$FJ!PUTm9h+BuBhIlgpq#>!_1pK3)PQC61xlCXL0B+S=Bqa6EdkzvrNh z%9j&J56|&u{Bf!wC>@$w_I@U#F{!a#h+1<~>1$KZt*@8vg<~P_eJrE9jgEIpnBB=Z zyM;aZxT!|nid;$;(Jrn`{+h|QL`0lQL@r*8;goeFv4!E!nV)e4lv#*x!-Pd8TcuCx z&lWl^jz_Mf!!BXFj_PGYemjYf)%J%~j-0+Gycm#i}@Lu2|y}Y$xipYe< zJ&1uiL$7Lu925NY#PaUW_q3o42EdgytI!NChR12k3LcRIB8VA?A6nn4JTm5$v7nb zYg=8-RcX`6m`BmvoR=yoGJ|KUFxX&FABCr*=D|f$gfU}SWh~2}c7zZu&1qX?{1Flz zJHQnTPnxnerGu32{h+>IFs^pKZ8{JVcdT~s?#Xhk?7JK>T>)>7(b7qZSb%0v z@fd#qq-tto;*e(l>!6Dn;WR?e*S}N~H?^_K&LyM8xDXx(R}s_^@lxEhG_y5ohJKe( z$Zw-m)46td=s%wRTl^p|AQt3)jZxQipB((Zn?OSiAiWMnuOamRi5_QqI&Fy9a!`)a zr>bzy*89Jr|HKUTwt7IxpCXkSvA&y30Ahjd1Gj?t96YU9F(X4}adYvVLMPt+lcsF+ zD|KTD+Jcss;c+v#t-_>9an!+yr&FMUj@HNivb&?z=`rqeqRT_W5lOvKr20N5>tYVow!p^NZ3ML7w%)0{jkgCa?A zMRDDrQiQ^&;)k*n8rr6GYMxGiYBaM_>%6XuQ;4uk=eUMlB0TWv1W3g_*vZT4jKbbs z4Ib*ad(8H$tM4uS6p7jsv zBN62Z&NcGBiBP{UZ0xb`Z3d*Q7bgZR?plA6<1aus=#Mi|s9YTNM2#%Qr!B0d zb$IsB>oE(GRx}+OG1P*&a>nuU7uznfb!fSA$wSxA8r@lgJo5GQ&%f`p-pwQS^((4P z3jch8dE8HBOGf^zFvDNUUZ8P{F8NOUG_hPAya(ld4M!#*33%EG0gjziPv}JcJkxh! zHQ`E8I$eW(zdOUDc)%(gT&9j9xydhg#_;n|?k2{Y+;~eRzY4d4GmztR+X15qE}r^< zQ6%Xmtxd$6_g)4}2##}wFvK(pgWiOjS~p6xOno`hEu;d{42lrxZJi^>ethfjhRI@Z z9b~aI0eL*JQ)Rqtn1r|@d7;z$L0__ULxAi6qJZ4FP!DE#n00=(LyQ;m>av7PT3A*SB{QaTHYokV&5hjvM>0h7fL~40{@7W zidl*U$YkAs6?2MNDbMJD7NPR;hTQ0F(qWn~DH!cPZ!akTL;~df?BtVavp$^q`+Z`glu93|cY==qQo6o2hs&b=H2zzy{{fimcNqWx literal 0 HcmV?d00001 From d2bdc022fb9386149ccdedd8d5a1778674607d3e Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Mon, 30 Jun 2025 10:01:31 -0700 Subject: [PATCH 06/30] Added sslcontext to SSE --- client/pom.xml | 4 +- .../io/split/client/SplitFactoryImpl.java | 45 +++++++++++-------- okhttp-modules/pom.xml | 4 +- pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- testing/pom.xml | 2 +- 7 files changed, 34 insertions(+), 27 deletions(-) diff --git a/client/pom.xml b/client/pom.xml index d0ae4a78..12441eb9 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,9 +5,9 @@ io.split.client java-client-parent - 4.16.0 + 4.17.0-rc1 - 4.16.0 + 4.17.0-rc1 java-client jar Java Client diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 978f1603..2e1ffe78 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -523,24 +523,7 @@ protected static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClie SDKMetadata sdkMetadata, RequestDecorator requestDecorator) throws URISyntaxException { - SSLContext sslContext; - if (config.proxyMTLSAuth() != null) { - _log.debug("Proxy setup using mTLS"); - try { - KeyStore keyStore = KeyStore.getInstance("PKCS12"); - InputStream keystoreStream = java.nio.file.Files.newInputStream(Paths.get(config.proxyMTLSAuth().getP12File())); - keyStore.load(keystoreStream, config.proxyMTLSAuth().getP12FilePassKey().toCharArray()); - sslContext = SSLContexts.custom() - .loadKeyMaterial(keyStore, config.proxyMTLSAuth().getP12FilePassKey().toCharArray()) - .build(); - } catch (Exception e) { - _log.error("Exception caught while processing p12 file for Proxy mTLS auth: ", e); - _log.warn("Ignoring p12 mTLS config and switching to default context"); - sslContext = SSLContexts.createSystemDefault(); - } - } else { - sslContext = SSLContexts.createSystemDefault(); - } + SSLContext sslContext = buildSSLContext(config); SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create() .setSslContext(sslContext) @@ -585,8 +568,10 @@ private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitCli .setConnectTimeout(Timeout.ofMilliseconds(SSE_CONNECT_TIMEOUT)) .build(); + SSLContext sslContext = buildSSLContext(config); + SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create() - .setSslContext(SSLContexts.createSystemDefault()) + .setSslContext(sslContext) .setTlsVersions(TLS.V_1_1, TLS.V_1_2) .build(); @@ -613,6 +598,28 @@ private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitCli return httpClientbuilder.build(); } + private static SSLContext buildSSLContext(SplitClientConfig config) { + SSLContext sslContext; + if (config.proxyMTLSAuth() != null) { + _log.debug("Proxy setup using mTLS"); + try { + KeyStore keyStore = KeyStore.getInstance("PKCS12"); + InputStream keystoreStream = java.nio.file.Files.newInputStream(Paths.get(config.proxyMTLSAuth().getP12File())); + keyStore.load(keystoreStream, config.proxyMTLSAuth().getP12FilePassKey().toCharArray()); + sslContext = SSLContexts.custom() + .loadKeyMaterial(keyStore, config.proxyMTLSAuth().getP12FilePassKey().toCharArray()) + .build(); + } catch (Exception e) { + _log.error("Exception caught while processing p12 file for Proxy mTLS auth: ", e); + _log.warn("Ignoring p12 mTLS config and switching to default context"); + sslContext = SSLContexts.createSystemDefault(); + } + } else { + sslContext = SSLContexts.createSystemDefault(); + } + return sslContext; + } + private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, SplitClientConfig config) { _log.info("Initializing Split SDK with proxy settings"); DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(config.proxy()); diff --git a/okhttp-modules/pom.xml b/okhttp-modules/pom.xml index a8645f9c..a474be3a 100644 --- a/okhttp-modules/pom.xml +++ b/okhttp-modules/pom.xml @@ -5,10 +5,10 @@ java-client-parent io.split.client - 4.16.0 + 4.17.0-rc1 4.0.0 - 4.16.0 + 4.17.0-rc1 okhttp-modules jar http-modules diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index 21b0bdac..b67933fe 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.16.0 + 4.17.0-rc1 2.1.0 diff --git a/pom.xml b/pom.xml index 7b21f1ec..5650bbc4 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.16.0 + 4.17.0-rc1 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index 301739ce..679f5502 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.16.0 + 4.17.0-rc1 redis-wrapper 3.1.1 diff --git a/testing/pom.xml b/testing/pom.xml index 0fae6cdf..9c01ba09 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -9,7 +9,7 @@ java-client-testing jar - 4.16.0 + 4.17.0-rc1 Java Client For Testing Testing suite for Java SDK for Split From 0489c0d14f040970f17f3ac36f35b2134cbb470f Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Mon, 30 Jun 2025 13:49:04 -0700 Subject: [PATCH 07/30] Added auto refresh proxy token --- .../client/HttpClientDynamicCredentials.java | 25 ++++++++++++++++ .../io/split/client/ProxyRuntimeStorage.java | 10 +++++++ .../io/split/client/SplitClientConfig.java | 26 ++++++++--------- .../io/split/client/SplitFactoryImpl.java | 9 ++---- .../split/client/SplitClientConfigTest.java | 29 ++++++++++++++++--- .../io/split/client/SplitFactoryImplTest.java | 4 ++- 6 files changed, 78 insertions(+), 25 deletions(-) create mode 100644 client/src/main/java/io/split/client/HttpClientDynamicCredentials.java create mode 100644 client/src/main/java/io/split/client/ProxyRuntimeStorage.java diff --git a/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java b/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java new file mode 100644 index 00000000..f7c84f6b --- /dev/null +++ b/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java @@ -0,0 +1,25 @@ +package io.split.client; + +import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.BearerToken; +import org.apache.hc.client5.http.auth.Credentials; +import org.apache.hc.core5.http.protocol.HttpContext; + +class HttpClientDynamicCredentials implements org.apache.hc.client5.http.auth.CredentialsProvider { + + private final ProxyRuntimeStorage _proxyRuntimeStorage; + + public HttpClientDynamicCredentials (ProxyRuntimeStorage proxyRuntimeStorage) { + _proxyRuntimeStorage = proxyRuntimeStorage; + } + + @Override + public Credentials getCredentials(AuthScope authScope, HttpContext context) { + + // This Provider is invoked every time a request is made. + // This should invoke a user-custom provider responsible for: + return new BearerToken(_proxyRuntimeStorage.getJwtToken()); + } + +} + diff --git a/client/src/main/java/io/split/client/ProxyRuntimeStorage.java b/client/src/main/java/io/split/client/ProxyRuntimeStorage.java new file mode 100644 index 00000000..e640be64 --- /dev/null +++ b/client/src/main/java/io/split/client/ProxyRuntimeStorage.java @@ -0,0 +1,10 @@ +package io.split.client; + +public interface ProxyRuntimeStorage +{ + /** + * Get the additional headers needed for all http operations + * @return HashMap of addition headers + */ + String getJwtToken(); +} diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index 6c388b2d..668eb7c3 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -91,7 +91,7 @@ public static class HttpScheme { private final HttpHost _proxy; private final String _proxyUsername; private final String _proxyPassword; - private final String _proxyToken; + private final ProxyRuntimeStorage _proxyRuntimeStorage; private final ProxyMTLSAuth _proxyMtlsAuth; // To be set during startup @@ -126,7 +126,7 @@ private SplitClientConfig(String endpoint, HttpHost proxy, String proxyUsername, String proxyPassword, - String proxyToken, + ProxyRuntimeStorage proxyRuntimeStorage, ProxyMTLSAuth proxyMtlsAuth, int eventsQueueSize, long eventSendIntervalInMillis, @@ -181,7 +181,7 @@ private SplitClientConfig(String endpoint, _proxy = proxy; _proxyUsername = proxyUsername; _proxyPassword = proxyPassword; - _proxyToken = proxyToken; + _proxyRuntimeStorage = proxyRuntimeStorage; _proxyMtlsAuth = proxyMtlsAuth; _eventsQueueSize = eventsQueueSize; _eventSendIntervalInMillis = eventSendIntervalInMillis; @@ -314,8 +314,8 @@ public String proxyPassword() { return _proxyPassword; } - public String proxyToken() { - return _proxyToken; + public ProxyRuntimeStorage proxyRuntimeStorage() { + return _proxyRuntimeStorage; } public ProxyMTLSAuth proxyMTLSAuth() { @@ -463,7 +463,7 @@ public static final class Builder { private String _proxyScheme = HttpScheme.HTTP; private String _proxyUsername; private String _proxyPassword; - private String _proxyToken; + private ProxyRuntimeStorage _proxyRuntimeStorage; private ProxyMTLSAuth _proxyMtlsAuth; private int _eventsQueueSize = 500; private long _eventSendIntervalInMillis = 30 * (long)1000; @@ -813,11 +813,11 @@ public Builder proxyPassword(String proxyPassword) { /** * Set the token for authentication against the proxy (if proxy settings are enabled). (Optional). * - * @param proxyToken + * @param proxyRuntimeStorage * @return this builder */ - public Builder proxyToken(String proxyToken) { - _proxyToken = proxyToken; + public Builder proxyRuntimeStorage(ProxyRuntimeStorage proxyRuntimeStorage) { + _proxyRuntimeStorage = proxyRuntimeStorage; return this; } @@ -1161,11 +1161,11 @@ private void verifyProxy() { throw new IllegalArgumentException("Proxy scheme must be either http or https."); } - if (_proxyUsername == null && _proxyToken == null && _proxyMtlsAuth == null) { + if (_proxyUsername == null && _proxyRuntimeStorage == null && _proxyMtlsAuth == null) { return; } - if (_proxyUsername != null && _proxyToken != null) { + if (_proxyUsername != null && _proxyRuntimeStorage != null) { throw new IllegalArgumentException("Proxy user and Proxy token params are updated, set only one param."); } @@ -1173,7 +1173,7 @@ private void verifyProxy() { throw new IllegalArgumentException("Proxy user and Proxy mTLS params are updated, set only one param."); } - if (_proxyToken != null && _proxyMtlsAuth != null) { + if (_proxyRuntimeStorage != null && _proxyMtlsAuth != null) { throw new IllegalArgumentException("Proxy token and Proxy mTLS params are updated, set only one param."); } @@ -1223,7 +1223,7 @@ public SplitClientConfig build() { proxy(), _proxyUsername, _proxyPassword, - _proxyToken, + _proxyRuntimeStorage, _proxyMtlsAuth, _eventsQueueSize, _eventSendIntervalInMillis, diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 2e1ffe78..b5b3dc80 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -92,7 +92,6 @@ import io.split.telemetry.synchronizer.TelemetrySynchronizer; import org.apache.hc.client5.http.auth.AuthScope; -import org.apache.hc.client5.http.auth.BearerToken; import org.apache.hc.client5.http.auth.Credentials; import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; import org.apache.hc.client5.http.config.RequestConfig; @@ -635,13 +634,9 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, httpClientbuilder.setDefaultCredentialsProvider(credsProvider); } - if (config.proxyToken() != null) { + if (config.proxyRuntimeStorage().getJwtToken() != null) { _log.debug("Proxy setup using token"); - BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); - AuthScope siteScope = new AuthScope(config.proxy().getHostName(), config.proxy().getPort()); - Credentials siteCreds = new BearerToken(config.proxyToken()); - credsProvider.setCredentials(siteScope, siteCreds); - httpClientbuilder.setDefaultCredentialsProvider(credsProvider); + httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials(config.proxyRuntimeStorage())); } return httpClientbuilder; diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index ebb4803b..131d8330 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -273,12 +273,19 @@ public void checkProxyParams() { Assert.assertEquals("user", config.proxyUsername()); Assert.assertEquals("pass", config.proxyPassword()); + ProxyRuntimeStorage proxyRuntimeStorage = new ProxyRuntimeStorage() { + @Override + public String getJwtToken() { + return "my-token"; + } + }; + config = SplitClientConfig.builder() .proxyHost("proxy-host") .proxyPort(8888) - .proxyToken("my-token") + .proxyRuntimeStorage(proxyRuntimeStorage) .build(); - Assert.assertEquals("my-token", config.proxyToken()); + Assert.assertEquals(proxyRuntimeStorage, config.proxyRuntimeStorage()); config = SplitClientConfig.builder() .proxyHost("proxy-host") @@ -300,12 +307,19 @@ public void cannotUseInvalidHttpScheme() { @Test(expected = IllegalArgumentException.class) public void cannotUseProxyTokenAndProxyUsername() { + ProxyRuntimeStorage proxyRuntimeStorage = new ProxyRuntimeStorage() { + @Override + public String getJwtToken() { + return "my-token"; + } + }; + SplitClientConfig.builder() .proxyHost("proxy-host") .proxyPort(8888) .proxyUsername("user") .proxyPassword("pass") - .proxyToken("my-token") + .proxyRuntimeStorage(proxyRuntimeStorage) .build(); } @@ -322,10 +336,17 @@ public void cannotUseProxyUserAndProxyMtls() { @Test(expected = IllegalArgumentException.class) public void cannotUseProxyTokenAndProxyMtls() { + ProxyRuntimeStorage proxyRuntimeStorage = new ProxyRuntimeStorage() { + @Override + public String getJwtToken() { + return "my-token"; + } + }; + SplitClientConfig.builder() .proxyHost("proxy-host") .proxyPort(8888) - .proxyToken("my-token") + .proxyRuntimeStorage(proxyRuntimeStorage) .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build()) .build(); } diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index 4597b615..62018ed7 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -21,6 +21,7 @@ import org.apache.hc.core5.http.config.Registry; import org.awaitility.Awaitility; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; import static org.mockito.Mockito.when; @@ -151,6 +152,7 @@ public void testFactoryInstantiationWithProxyCredentials() throws Exception { splitFactory.destroy(); } + @Ignore @Test public void testFactoryInstantiationWithProxyToken() throws Exception { SplitClientConfig splitClientConfig = SplitClientConfig.builder() @@ -162,7 +164,7 @@ public void testFactoryInstantiationWithProxyToken() throws Exception { .authServiceURL(AUTH_SERVICE) .setBlockUntilReadyTimeout(1000) .proxyPort(6060) - .proxyToken("123456789") +// .proxyToken("123456789") .proxyHost(ENDPOINT) .build(); SplitFactoryImpl splitFactory2 = new SplitFactoryImpl(API_KEY, splitClientConfig); From 4a86a3d556dd368ec6767baeeff0e30bb0b90609 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Mon, 30 Jun 2025 13:56:53 -0700 Subject: [PATCH 08/30] disable test --- client/src/main/java/io/split/client/SplitFactoryImpl.java | 2 +- .../src/test/java/io/split/client/SplitFactoryImplTest.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index b5b3dc80..64874c36 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -634,7 +634,7 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, httpClientbuilder.setDefaultCredentialsProvider(credsProvider); } - if (config.proxyRuntimeStorage().getJwtToken() != null) { + if (config.proxyRuntimeStorage() != null) { _log.debug("Proxy setup using token"); httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials(config.proxyRuntimeStorage())); } diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index 62018ed7..5731b856 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -151,8 +151,7 @@ public void testFactoryInstantiationWithProxyCredentials() throws Exception { splitFactory.destroy(); } - - @Ignore +/* @Test public void testFactoryInstantiationWithProxyToken() throws Exception { SplitClientConfig splitClientConfig = SplitClientConfig.builder() @@ -191,7 +190,7 @@ public void testFactoryInstantiationWithProxyToken() throws Exception { splitFactory2.destroy(); } - +*/ @Test public void testFactoryInstantiationWithProxyMtls() throws Exception { SplitClientConfig splitClientConfig = SplitClientConfig.builder() From a5a92f8c705233d18b26d39a863dc115bc694799 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Mon, 30 Jun 2025 14:07:28 -0700 Subject: [PATCH 09/30] disabled test --- .../java/io/split/client/SplitFactoryImplTest.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index 5731b856..2b302bad 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -151,9 +151,16 @@ public void testFactoryInstantiationWithProxyCredentials() throws Exception { splitFactory.destroy(); } -/* + @Test public void testFactoryInstantiationWithProxyToken() throws Exception { + class MyProxyRuntimeStorage implements ProxyRuntimeStorage { + @Override + public String getJwtToken() { + return "123456789"; + } + }; + SplitClientConfig splitClientConfig = SplitClientConfig.builder() .enableDebug() .impressionsMode(ImpressionsManager.Mode.DEBUG) @@ -163,7 +170,7 @@ public void testFactoryInstantiationWithProxyToken() throws Exception { .authServiceURL(AUTH_SERVICE) .setBlockUntilReadyTimeout(1000) .proxyPort(6060) -// .proxyToken("123456789") + .proxyRuntimeStorage(new MyProxyRuntimeStorage()) .proxyHost(ENDPOINT) .build(); SplitFactoryImpl splitFactory2 = new SplitFactoryImpl(API_KEY, splitClientConfig); @@ -190,7 +197,7 @@ public void testFactoryInstantiationWithProxyToken() throws Exception { splitFactory2.destroy(); } -*/ + @Test public void testFactoryInstantiationWithProxyMtls() throws Exception { SplitClientConfig splitClientConfig = SplitClientConfig.builder() From 32f5a117d78c580d6f6ec281ba0c1fcd62314756 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Mon, 30 Jun 2025 14:07:57 -0700 Subject: [PATCH 10/30] disabled test --- .../src/test/java/io/split/client/SplitFactoryImplTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index 2b302bad..008df7f4 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -151,7 +151,7 @@ public void testFactoryInstantiationWithProxyCredentials() throws Exception { splitFactory.destroy(); } - +/* @Test public void testFactoryInstantiationWithProxyToken() throws Exception { class MyProxyRuntimeStorage implements ProxyRuntimeStorage { @@ -197,7 +197,7 @@ public String getJwtToken() { splitFactory2.destroy(); } - +*/ @Test public void testFactoryInstantiationWithProxyMtls() throws Exception { SplitClientConfig splitClientConfig = SplitClientConfig.builder() From ce3aec5cdcb92d47a18df4ae4b87a890b9c650ed Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Mon, 30 Jun 2025 14:30:42 -0700 Subject: [PATCH 11/30] renamed interface --- .../client/HttpClientDynamicCredentials.java | 8 +++--- ...Storage.java => ProxyRuntimeProvider.java} | 2 +- .../io/split/client/SplitClientConfig.java | 26 +++++++++---------- .../split/client/SplitClientConfigTest.java | 14 +++++----- 4 files changed, 25 insertions(+), 25 deletions(-) rename client/src/main/java/io/split/client/{ProxyRuntimeStorage.java => ProxyRuntimeProvider.java} (82%) diff --git a/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java b/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java index f7c84f6b..bdf0cff8 100644 --- a/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java +++ b/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java @@ -7,10 +7,10 @@ class HttpClientDynamicCredentials implements org.apache.hc.client5.http.auth.CredentialsProvider { - private final ProxyRuntimeStorage _proxyRuntimeStorage; + private final ProxyRuntimeProvider _proxyRuntimeProvider; - public HttpClientDynamicCredentials (ProxyRuntimeStorage proxyRuntimeStorage) { - _proxyRuntimeStorage = proxyRuntimeStorage; + public HttpClientDynamicCredentials (ProxyRuntimeProvider proxyRuntimeProvider) { + _proxyRuntimeProvider = proxyRuntimeProvider; } @Override @@ -18,7 +18,7 @@ public Credentials getCredentials(AuthScope authScope, HttpContext context) { // This Provider is invoked every time a request is made. // This should invoke a user-custom provider responsible for: - return new BearerToken(_proxyRuntimeStorage.getJwtToken()); + return new BearerToken(_proxyRuntimeProvider.getJwtToken()); } } diff --git a/client/src/main/java/io/split/client/ProxyRuntimeStorage.java b/client/src/main/java/io/split/client/ProxyRuntimeProvider.java similarity index 82% rename from client/src/main/java/io/split/client/ProxyRuntimeStorage.java rename to client/src/main/java/io/split/client/ProxyRuntimeProvider.java index e640be64..ca30c7f2 100644 --- a/client/src/main/java/io/split/client/ProxyRuntimeStorage.java +++ b/client/src/main/java/io/split/client/ProxyRuntimeProvider.java @@ -1,6 +1,6 @@ package io.split.client; -public interface ProxyRuntimeStorage +public interface ProxyRuntimeProvider { /** * Get the additional headers needed for all http operations diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index 668eb7c3..ef798847 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -91,7 +91,7 @@ public static class HttpScheme { private final HttpHost _proxy; private final String _proxyUsername; private final String _proxyPassword; - private final ProxyRuntimeStorage _proxyRuntimeStorage; + private final ProxyRuntimeProvider _proxyRuntimeProvider; private final ProxyMTLSAuth _proxyMtlsAuth; // To be set during startup @@ -126,7 +126,7 @@ private SplitClientConfig(String endpoint, HttpHost proxy, String proxyUsername, String proxyPassword, - ProxyRuntimeStorage proxyRuntimeStorage, + ProxyRuntimeProvider proxyRuntimeProvider, ProxyMTLSAuth proxyMtlsAuth, int eventsQueueSize, long eventSendIntervalInMillis, @@ -181,7 +181,7 @@ private SplitClientConfig(String endpoint, _proxy = proxy; _proxyUsername = proxyUsername; _proxyPassword = proxyPassword; - _proxyRuntimeStorage = proxyRuntimeStorage; + _proxyRuntimeProvider = proxyRuntimeProvider; _proxyMtlsAuth = proxyMtlsAuth; _eventsQueueSize = eventsQueueSize; _eventSendIntervalInMillis = eventSendIntervalInMillis; @@ -314,8 +314,8 @@ public String proxyPassword() { return _proxyPassword; } - public ProxyRuntimeStorage proxyRuntimeStorage() { - return _proxyRuntimeStorage; + public ProxyRuntimeProvider proxyRuntimeStorage() { + return _proxyRuntimeProvider; } public ProxyMTLSAuth proxyMTLSAuth() { @@ -463,7 +463,7 @@ public static final class Builder { private String _proxyScheme = HttpScheme.HTTP; private String _proxyUsername; private String _proxyPassword; - private ProxyRuntimeStorage _proxyRuntimeStorage; + private ProxyRuntimeProvider _proxyRuntimeProvider; private ProxyMTLSAuth _proxyMtlsAuth; private int _eventsQueueSize = 500; private long _eventSendIntervalInMillis = 30 * (long)1000; @@ -813,11 +813,11 @@ public Builder proxyPassword(String proxyPassword) { /** * Set the token for authentication against the proxy (if proxy settings are enabled). (Optional). * - * @param proxyRuntimeStorage + * @param proxyRuntimeProvider * @return this builder */ - public Builder proxyRuntimeStorage(ProxyRuntimeStorage proxyRuntimeStorage) { - _proxyRuntimeStorage = proxyRuntimeStorage; + public Builder proxyRuntimeStorage(ProxyRuntimeProvider proxyRuntimeProvider) { + _proxyRuntimeProvider = proxyRuntimeProvider; return this; } @@ -1161,11 +1161,11 @@ private void verifyProxy() { throw new IllegalArgumentException("Proxy scheme must be either http or https."); } - if (_proxyUsername == null && _proxyRuntimeStorage == null && _proxyMtlsAuth == null) { + if (_proxyUsername == null && _proxyRuntimeProvider == null && _proxyMtlsAuth == null) { return; } - if (_proxyUsername != null && _proxyRuntimeStorage != null) { + if (_proxyUsername != null && _proxyRuntimeProvider != null) { throw new IllegalArgumentException("Proxy user and Proxy token params are updated, set only one param."); } @@ -1173,7 +1173,7 @@ private void verifyProxy() { throw new IllegalArgumentException("Proxy user and Proxy mTLS params are updated, set only one param."); } - if (_proxyRuntimeStorage != null && _proxyMtlsAuth != null) { + if (_proxyRuntimeProvider != null && _proxyMtlsAuth != null) { throw new IllegalArgumentException("Proxy token and Proxy mTLS params are updated, set only one param."); } @@ -1223,7 +1223,7 @@ public SplitClientConfig build() { proxy(), _proxyUsername, _proxyPassword, - _proxyRuntimeStorage, + _proxyRuntimeProvider, _proxyMtlsAuth, _eventsQueueSize, _eventSendIntervalInMillis, diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index 131d8330..25de5498 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -273,7 +273,7 @@ public void checkProxyParams() { Assert.assertEquals("user", config.proxyUsername()); Assert.assertEquals("pass", config.proxyPassword()); - ProxyRuntimeStorage proxyRuntimeStorage = new ProxyRuntimeStorage() { + ProxyRuntimeProvider proxyRuntimeProvider = new ProxyRuntimeProvider() { @Override public String getJwtToken() { return "my-token"; @@ -283,9 +283,9 @@ public String getJwtToken() { config = SplitClientConfig.builder() .proxyHost("proxy-host") .proxyPort(8888) - .proxyRuntimeStorage(proxyRuntimeStorage) + .proxyRuntimeStorage(proxyRuntimeProvider) .build(); - Assert.assertEquals(proxyRuntimeStorage, config.proxyRuntimeStorage()); + Assert.assertEquals(proxyRuntimeProvider, config.proxyRuntimeStorage()); config = SplitClientConfig.builder() .proxyHost("proxy-host") @@ -307,7 +307,7 @@ public void cannotUseInvalidHttpScheme() { @Test(expected = IllegalArgumentException.class) public void cannotUseProxyTokenAndProxyUsername() { - ProxyRuntimeStorage proxyRuntimeStorage = new ProxyRuntimeStorage() { + ProxyRuntimeProvider proxyRuntimeProvider = new ProxyRuntimeProvider() { @Override public String getJwtToken() { return "my-token"; @@ -319,7 +319,7 @@ public String getJwtToken() { .proxyPort(8888) .proxyUsername("user") .proxyPassword("pass") - .proxyRuntimeStorage(proxyRuntimeStorage) + .proxyRuntimeStorage(proxyRuntimeProvider) .build(); } @@ -336,7 +336,7 @@ public void cannotUseProxyUserAndProxyMtls() { @Test(expected = IllegalArgumentException.class) public void cannotUseProxyTokenAndProxyMtls() { - ProxyRuntimeStorage proxyRuntimeStorage = new ProxyRuntimeStorage() { + ProxyRuntimeProvider proxyRuntimeProvider = new ProxyRuntimeProvider() { @Override public String getJwtToken() { return "my-token"; @@ -346,7 +346,7 @@ public String getJwtToken() { SplitClientConfig.builder() .proxyHost("proxy-host") .proxyPort(8888) - .proxyRuntimeStorage(proxyRuntimeStorage) + .proxyRuntimeStorage(proxyRuntimeProvider) .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build()) .build(); } From 4662ee7fe1296c80d248583488116e24b2345e9c Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 1 Jul 2025 08:22:48 -0700 Subject: [PATCH 12/30] Fixed config property and test --- .../io/split/client/SplitClientConfig.java | 4 ++-- .../java/io/split/client/SplitFactoryImpl.java | 4 ++-- .../io/split/client/SplitClientConfigTest.java | 8 ++++---- .../io/split/client/SplitFactoryImplTest.java | 18 +++++++++--------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index ef798847..ef75b2cc 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -314,7 +314,7 @@ public String proxyPassword() { return _proxyPassword; } - public ProxyRuntimeProvider proxyRuntimeStorage() { + public ProxyRuntimeProvider proxyRuntimeProvider() { return _proxyRuntimeProvider; } @@ -816,7 +816,7 @@ public Builder proxyPassword(String proxyPassword) { * @param proxyRuntimeProvider * @return this builder */ - public Builder proxyRuntimeStorage(ProxyRuntimeProvider proxyRuntimeProvider) { + public Builder proxyRuntimeProvider(ProxyRuntimeProvider proxyRuntimeProvider) { _proxyRuntimeProvider = proxyRuntimeProvider; return this; } diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 64874c36..13d925ad 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -634,9 +634,9 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, httpClientbuilder.setDefaultCredentialsProvider(credsProvider); } - if (config.proxyRuntimeStorage() != null) { + if (config.proxyRuntimeProvider() != null) { _log.debug("Proxy setup using token"); - httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials(config.proxyRuntimeStorage())); + httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials(config.proxyRuntimeProvider())); } return httpClientbuilder; diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index 25de5498..f72fb84f 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -283,9 +283,9 @@ public String getJwtToken() { config = SplitClientConfig.builder() .proxyHost("proxy-host") .proxyPort(8888) - .proxyRuntimeStorage(proxyRuntimeProvider) + .proxyRuntimeProvider(proxyRuntimeProvider) .build(); - Assert.assertEquals(proxyRuntimeProvider, config.proxyRuntimeStorage()); + Assert.assertEquals(proxyRuntimeProvider, config.proxyRuntimeProvider()); config = SplitClientConfig.builder() .proxyHost("proxy-host") @@ -319,7 +319,7 @@ public String getJwtToken() { .proxyPort(8888) .proxyUsername("user") .proxyPassword("pass") - .proxyRuntimeStorage(proxyRuntimeProvider) + .proxyRuntimeProvider(proxyRuntimeProvider) .build(); } @@ -346,7 +346,7 @@ public String getJwtToken() { SplitClientConfig.builder() .proxyHost("proxy-host") .proxyPort(8888) - .proxyRuntimeStorage(proxyRuntimeProvider) + .proxyRuntimeProvider(proxyRuntimeProvider) .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build()) .build(); } diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index 008df7f4..072eed25 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -151,10 +151,10 @@ public void testFactoryInstantiationWithProxyCredentials() throws Exception { splitFactory.destroy(); } -/* + @Test public void testFactoryInstantiationWithProxyToken() throws Exception { - class MyProxyRuntimeStorage implements ProxyRuntimeStorage { + class MyProxyRuntimeProvider implements ProxyRuntimeProvider { @Override public String getJwtToken() { return "123456789"; @@ -170,7 +170,7 @@ public String getJwtToken() { .authServiceURL(AUTH_SERVICE) .setBlockUntilReadyTimeout(1000) .proxyPort(6060) - .proxyRuntimeStorage(new MyProxyRuntimeStorage()) + .proxyRuntimeProvider(new MyProxyRuntimeProvider()) .proxyHost(ENDPOINT) .build(); SplitFactoryImpl splitFactory2 = new SplitFactoryImpl(API_KEY, splitClientConfig); @@ -187,17 +187,17 @@ public String getJwtToken() { Field credentialsProviderField2 = InternalHttp2.getDeclaredField("credentialsProvider"); credentialsProviderField2.setAccessible(true); - BasicCredentialsProvider credentialsProvider2 = (BasicCredentialsProvider) credentialsProviderField2.get(InternalHttp2.cast(httpClientField2.get(client2))); + HttpClientDynamicCredentials credentialsProvider2 = (HttpClientDynamicCredentials) credentialsProviderField2.get(InternalHttp2.cast(httpClientField2.get(client2))); - Field credMapField2 = BasicCredentialsProvider.class.getDeclaredField("credMap"); - credMapField2.setAccessible(true); - ConcurrentHashMap credMap2 = (ConcurrentHashMap) credMapField2.get(credentialsProvider2); + Field proxyRuntimeField = HttpClientDynamicCredentials.class.getDeclaredField("_proxyRuntimeProvider"); + proxyRuntimeField.setAccessible(true); + MyProxyRuntimeProvider proxyRuntime = (MyProxyRuntimeProvider) proxyRuntimeField.get(credentialsProvider2); - Assert.assertEquals("123456789", credMap2.entrySet().stream().iterator().next().getValue().getToken()); + assertNotNull("123456789", proxyRuntime.getJwtToken()); splitFactory2.destroy(); } -*/ + @Test public void testFactoryInstantiationWithProxyMtls() throws Exception { SplitClientConfig splitClientConfig = SplitClientConfig.builder() From 61fe715491fb14ef91aa55aabc16fa82192c188f Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 1 Jul 2025 08:54:01 -0700 Subject: [PATCH 13/30] Rename config field --- .../client/HttpClientDynamicCredentials.java | 8 +- ...der.java => ProxyCredentialsProvider.java} | 2 +- .../io/split/client/SplitClientConfig.java | 26 +- .../io/split/client/SplitFactoryImpl.java | 4 +- .../split/client/SplitClientConfigTest.java | 14 +- .../io/split/client/SplitFactoryImplTest.java | 10 +- testing/.github/CODEOWNERS | 1 + .../linter/checkstyle-suppressions.xml | 9 + testing/.github/linter/google-java-style.xml | 380 ++++++++++++++++++ 9 files changed, 421 insertions(+), 33 deletions(-) rename client/src/main/java/io/split/client/{ProxyRuntimeProvider.java => ProxyCredentialsProvider.java} (81%) create mode 100644 testing/.github/CODEOWNERS create mode 100644 testing/.github/linter/checkstyle-suppressions.xml create mode 100644 testing/.github/linter/google-java-style.xml diff --git a/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java b/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java index bdf0cff8..01a32362 100644 --- a/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java +++ b/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java @@ -7,10 +7,10 @@ class HttpClientDynamicCredentials implements org.apache.hc.client5.http.auth.CredentialsProvider { - private final ProxyRuntimeProvider _proxyRuntimeProvider; + private final ProxyCredentialsProvider _proxyCredentialsProvider; - public HttpClientDynamicCredentials (ProxyRuntimeProvider proxyRuntimeProvider) { - _proxyRuntimeProvider = proxyRuntimeProvider; + public HttpClientDynamicCredentials (ProxyCredentialsProvider proxyCredentialsProvider) { + _proxyCredentialsProvider = proxyCredentialsProvider; } @Override @@ -18,7 +18,7 @@ public Credentials getCredentials(AuthScope authScope, HttpContext context) { // This Provider is invoked every time a request is made. // This should invoke a user-custom provider responsible for: - return new BearerToken(_proxyRuntimeProvider.getJwtToken()); + return new BearerToken(_proxyCredentialsProvider.getJwtToken()); } } diff --git a/client/src/main/java/io/split/client/ProxyRuntimeProvider.java b/client/src/main/java/io/split/client/ProxyCredentialsProvider.java similarity index 81% rename from client/src/main/java/io/split/client/ProxyRuntimeProvider.java rename to client/src/main/java/io/split/client/ProxyCredentialsProvider.java index ca30c7f2..6fb595bc 100644 --- a/client/src/main/java/io/split/client/ProxyRuntimeProvider.java +++ b/client/src/main/java/io/split/client/ProxyCredentialsProvider.java @@ -1,6 +1,6 @@ package io.split.client; -public interface ProxyRuntimeProvider +public interface ProxyCredentialsProvider { /** * Get the additional headers needed for all http operations diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index ef75b2cc..603d5ef1 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -91,7 +91,7 @@ public static class HttpScheme { private final HttpHost _proxy; private final String _proxyUsername; private final String _proxyPassword; - private final ProxyRuntimeProvider _proxyRuntimeProvider; + private final ProxyCredentialsProvider _proxyCredentialsProvider; private final ProxyMTLSAuth _proxyMtlsAuth; // To be set during startup @@ -126,7 +126,7 @@ private SplitClientConfig(String endpoint, HttpHost proxy, String proxyUsername, String proxyPassword, - ProxyRuntimeProvider proxyRuntimeProvider, + ProxyCredentialsProvider proxyCredentialsProvider, ProxyMTLSAuth proxyMtlsAuth, int eventsQueueSize, long eventSendIntervalInMillis, @@ -181,7 +181,7 @@ private SplitClientConfig(String endpoint, _proxy = proxy; _proxyUsername = proxyUsername; _proxyPassword = proxyPassword; - _proxyRuntimeProvider = proxyRuntimeProvider; + _proxyCredentialsProvider = proxyCredentialsProvider; _proxyMtlsAuth = proxyMtlsAuth; _eventsQueueSize = eventsQueueSize; _eventSendIntervalInMillis = eventSendIntervalInMillis; @@ -314,8 +314,8 @@ public String proxyPassword() { return _proxyPassword; } - public ProxyRuntimeProvider proxyRuntimeProvider() { - return _proxyRuntimeProvider; + public ProxyCredentialsProvider proxyCredentialsProvider() { + return _proxyCredentialsProvider; } public ProxyMTLSAuth proxyMTLSAuth() { @@ -463,7 +463,7 @@ public static final class Builder { private String _proxyScheme = HttpScheme.HTTP; private String _proxyUsername; private String _proxyPassword; - private ProxyRuntimeProvider _proxyRuntimeProvider; + private ProxyCredentialsProvider _proxyCredentialsProvider; private ProxyMTLSAuth _proxyMtlsAuth; private int _eventsQueueSize = 500; private long _eventSendIntervalInMillis = 30 * (long)1000; @@ -813,11 +813,11 @@ public Builder proxyPassword(String proxyPassword) { /** * Set the token for authentication against the proxy (if proxy settings are enabled). (Optional). * - * @param proxyRuntimeProvider + * @param proxyCredentialsProvider * @return this builder */ - public Builder proxyRuntimeProvider(ProxyRuntimeProvider proxyRuntimeProvider) { - _proxyRuntimeProvider = proxyRuntimeProvider; + public Builder proxyCredentialsProvider(ProxyCredentialsProvider proxyCredentialsProvider) { + _proxyCredentialsProvider = proxyCredentialsProvider; return this; } @@ -1161,11 +1161,11 @@ private void verifyProxy() { throw new IllegalArgumentException("Proxy scheme must be either http or https."); } - if (_proxyUsername == null && _proxyRuntimeProvider == null && _proxyMtlsAuth == null) { + if (_proxyUsername == null && _proxyCredentialsProvider == null && _proxyMtlsAuth == null) { return; } - if (_proxyUsername != null && _proxyRuntimeProvider != null) { + if (_proxyUsername != null && _proxyCredentialsProvider != null) { throw new IllegalArgumentException("Proxy user and Proxy token params are updated, set only one param."); } @@ -1173,7 +1173,7 @@ private void verifyProxy() { throw new IllegalArgumentException("Proxy user and Proxy mTLS params are updated, set only one param."); } - if (_proxyRuntimeProvider != null && _proxyMtlsAuth != null) { + if (_proxyCredentialsProvider != null && _proxyMtlsAuth != null) { throw new IllegalArgumentException("Proxy token and Proxy mTLS params are updated, set only one param."); } @@ -1223,7 +1223,7 @@ public SplitClientConfig build() { proxy(), _proxyUsername, _proxyPassword, - _proxyRuntimeProvider, + _proxyCredentialsProvider, _proxyMtlsAuth, _eventsQueueSize, _eventSendIntervalInMillis, diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 13d925ad..4da2f503 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -634,9 +634,9 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, httpClientbuilder.setDefaultCredentialsProvider(credsProvider); } - if (config.proxyRuntimeProvider() != null) { + if (config.proxyCredentialsProvider() != null) { _log.debug("Proxy setup using token"); - httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials(config.proxyRuntimeProvider())); + httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials(config.proxyCredentialsProvider())); } return httpClientbuilder; diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index f72fb84f..81ad9913 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -273,7 +273,7 @@ public void checkProxyParams() { Assert.assertEquals("user", config.proxyUsername()); Assert.assertEquals("pass", config.proxyPassword()); - ProxyRuntimeProvider proxyRuntimeProvider = new ProxyRuntimeProvider() { + ProxyCredentialsProvider proxyCredentialsProvider = new ProxyCredentialsProvider() { @Override public String getJwtToken() { return "my-token"; @@ -283,9 +283,9 @@ public String getJwtToken() { config = SplitClientConfig.builder() .proxyHost("proxy-host") .proxyPort(8888) - .proxyRuntimeProvider(proxyRuntimeProvider) + .proxyCredentialsProvider(proxyCredentialsProvider) .build(); - Assert.assertEquals(proxyRuntimeProvider, config.proxyRuntimeProvider()); + Assert.assertEquals(proxyCredentialsProvider, config.proxyCredentialsProvider()); config = SplitClientConfig.builder() .proxyHost("proxy-host") @@ -307,7 +307,7 @@ public void cannotUseInvalidHttpScheme() { @Test(expected = IllegalArgumentException.class) public void cannotUseProxyTokenAndProxyUsername() { - ProxyRuntimeProvider proxyRuntimeProvider = new ProxyRuntimeProvider() { + ProxyCredentialsProvider proxyCredentialsProvider = new ProxyCredentialsProvider() { @Override public String getJwtToken() { return "my-token"; @@ -319,7 +319,7 @@ public String getJwtToken() { .proxyPort(8888) .proxyUsername("user") .proxyPassword("pass") - .proxyRuntimeProvider(proxyRuntimeProvider) + .proxyCredentialsProvider(proxyCredentialsProvider) .build(); } @@ -336,7 +336,7 @@ public void cannotUseProxyUserAndProxyMtls() { @Test(expected = IllegalArgumentException.class) public void cannotUseProxyTokenAndProxyMtls() { - ProxyRuntimeProvider proxyRuntimeProvider = new ProxyRuntimeProvider() { + ProxyCredentialsProvider proxyCredentialsProvider = new ProxyCredentialsProvider() { @Override public String getJwtToken() { return "my-token"; @@ -346,7 +346,7 @@ public String getJwtToken() { SplitClientConfig.builder() .proxyHost("proxy-host") .proxyPort(8888) - .proxyRuntimeProvider(proxyRuntimeProvider) + .proxyCredentialsProvider(proxyCredentialsProvider) .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build()) .build(); } diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index 072eed25..1214b246 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -11,7 +11,6 @@ import io.split.telemetry.synchronizer.TelemetrySynchronizer; import junit.framework.TestCase; import org.apache.hc.client5.http.auth.AuthScope; -import org.apache.hc.client5.http.auth.BearerToken; import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; import org.apache.hc.client5.http.impl.io.DefaultHttpClientConnectionOperator; @@ -21,7 +20,6 @@ import org.apache.hc.core5.http.config.Registry; import org.awaitility.Awaitility; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; import static org.mockito.Mockito.when; @@ -154,7 +152,7 @@ public void testFactoryInstantiationWithProxyCredentials() throws Exception { @Test public void testFactoryInstantiationWithProxyToken() throws Exception { - class MyProxyRuntimeProvider implements ProxyRuntimeProvider { + class MyProxyCredentialsProvider implements ProxyCredentialsProvider { @Override public String getJwtToken() { return "123456789"; @@ -170,7 +168,7 @@ public String getJwtToken() { .authServiceURL(AUTH_SERVICE) .setBlockUntilReadyTimeout(1000) .proxyPort(6060) - .proxyRuntimeProvider(new MyProxyRuntimeProvider()) + .proxyCredentialsProvider(new MyProxyCredentialsProvider()) .proxyHost(ENDPOINT) .build(); SplitFactoryImpl splitFactory2 = new SplitFactoryImpl(API_KEY, splitClientConfig); @@ -189,9 +187,9 @@ public String getJwtToken() { credentialsProviderField2.setAccessible(true); HttpClientDynamicCredentials credentialsProvider2 = (HttpClientDynamicCredentials) credentialsProviderField2.get(InternalHttp2.cast(httpClientField2.get(client2))); - Field proxyRuntimeField = HttpClientDynamicCredentials.class.getDeclaredField("_proxyRuntimeProvider"); + Field proxyRuntimeField = HttpClientDynamicCredentials.class.getDeclaredField("_proxyCredentialsProvider"); proxyRuntimeField.setAccessible(true); - MyProxyRuntimeProvider proxyRuntime = (MyProxyRuntimeProvider) proxyRuntimeField.get(credentialsProvider2); + MyProxyCredentialsProvider proxyRuntime = (MyProxyCredentialsProvider) proxyRuntimeField.get(credentialsProvider2); assertNotNull("123456789", proxyRuntime.getJwtToken()); diff --git a/testing/.github/CODEOWNERS b/testing/.github/CODEOWNERS new file mode 100644 index 00000000..9e319810 --- /dev/null +++ b/testing/.github/CODEOWNERS @@ -0,0 +1 @@ +* @splitio/sdk diff --git a/testing/.github/linter/checkstyle-suppressions.xml b/testing/.github/linter/checkstyle-suppressions.xml new file mode 100644 index 00000000..81d23539 --- /dev/null +++ b/testing/.github/linter/checkstyle-suppressions.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/testing/.github/linter/google-java-style.xml b/testing/.github/linter/google-java-style.xml new file mode 100644 index 00000000..e885305e --- /dev/null +++ b/testing/.github/linter/google-java-style.xml @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From e53c5d060aaea53410d7b57f857d5baf30a951b8 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 1 Jul 2025 11:04:22 -0700 Subject: [PATCH 14/30] polishing --- client/pom.xml | 6 +- .../io/split/client/SplitClientConfig.java | 9 +- .../io/split/client/SplitFactoryImpl.java | 11 +- okhttp-modules/pom.xml | 6 +- pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- testing/.github/CODEOWNERS | 1 - .../linter/checkstyle-suppressions.xml | 9 - testing/.github/linter/google-java-style.xml | 380 ------------------ testing/pom.xml | 4 +- 11 files changed, 23 insertions(+), 409 deletions(-) delete mode 100644 testing/.github/CODEOWNERS delete mode 100644 testing/.github/linter/checkstyle-suppressions.xml delete mode 100644 testing/.github/linter/google-java-style.xml diff --git a/client/pom.xml b/client/pom.xml index 567849d2..5310cfea 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,9 +5,9 @@ io.split.client java-client-parent - 4.17.0-rc1 + 4.17.0-rc2 - 4.17.0-rc1 + 4.17.0-rc2 java-client jar Java Client @@ -24,7 +24,7 @@ 0.8.0 true - true + false central false published diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index 603d5ef1..d314baa7 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -36,6 +36,9 @@ public class SplitClientConfig { public static final String TELEMETRY_ENDPOINT = "https://telemetry.split.io/api/v1"; public static class HttpScheme { + private HttpScheme() { + throw new IllegalStateException("Utility class"); + } public static final String HTTP = "http"; public static final String HTTPS = "https"; } @@ -1177,10 +1180,8 @@ private void verifyProxy() { throw new IllegalArgumentException("Proxy token and Proxy mTLS params are updated, set only one param."); } - if (_proxyMtlsAuth != null) { - if (_proxyMtlsAuth.getP12File() == null || _proxyMtlsAuth.getP12FilePassKey() == null) { - throw new IllegalArgumentException("Proxy mTLS must have p12 file path and name, and pass phrase."); - } + if (_proxyMtlsAuth != null && (_proxyMtlsAuth.getP12File() == null || _proxyMtlsAuth.getP12FilePassKey() == null)) { + throw new IllegalArgumentException("Proxy mTLS must have p12 file path and name, and pass phrase."); } } diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 4da2f503..e1a11dcf 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -520,7 +520,7 @@ public boolean isDestroyed() { protected static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClientConfig config, SDKMetadata sdkMetadata, RequestDecorator requestDecorator) - throws URISyntaxException { + throws URISyntaxException, IOException { SSLContext sslContext = buildSSLContext(config); @@ -562,7 +562,7 @@ protected static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClie } private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitClientConfig config, - SDKMetadata sdkMetadata) { + SDKMetadata sdkMetadata) throws IOException { RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(Timeout.ofMilliseconds(SSE_CONNECT_TIMEOUT)) .build(); @@ -597,13 +597,14 @@ private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitCli return httpClientbuilder.build(); } - private static SSLContext buildSSLContext(SplitClientConfig config) { + private static SSLContext buildSSLContext(SplitClientConfig config) throws IOException { SSLContext sslContext; if (config.proxyMTLSAuth() != null) { _log.debug("Proxy setup using mTLS"); + InputStream keystoreStream = null; try { KeyStore keyStore = KeyStore.getInstance("PKCS12"); - InputStream keystoreStream = java.nio.file.Files.newInputStream(Paths.get(config.proxyMTLSAuth().getP12File())); + keystoreStream = java.nio.file.Files.newInputStream(Paths.get(config.proxyMTLSAuth().getP12File())); keyStore.load(keystoreStream, config.proxyMTLSAuth().getP12FilePassKey().toCharArray()); sslContext = SSLContexts.custom() .loadKeyMaterial(keyStore, config.proxyMTLSAuth().getP12FilePassKey().toCharArray()) @@ -612,6 +613,8 @@ private static SSLContext buildSSLContext(SplitClientConfig config) { _log.error("Exception caught while processing p12 file for Proxy mTLS auth: ", e); _log.warn("Ignoring p12 mTLS config and switching to default context"); sslContext = SSLContexts.createSystemDefault(); + } finally { + keystoreStream.close(); } } else { sslContext = SSLContexts.createSystemDefault(); diff --git a/okhttp-modules/pom.xml b/okhttp-modules/pom.xml index f236d002..ff0bac2e 100644 --- a/okhttp-modules/pom.xml +++ b/okhttp-modules/pom.xml @@ -5,10 +5,10 @@ java-client-parent io.split.client - 4.17.0-rc1 + 4.17.0-rc2 4.0.0 - 4.17.0-rc1 + 4.17.0-rc2 okhttp-modules jar http-modules @@ -25,7 +25,7 @@ 0.8.0 true - true + false central false published diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index da96cc3a..0353d0c5 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.17.0-rc1 + 4.17.0-rc2 2.1.0 diff --git a/pom.xml b/pom.xml index 65a92436..cabb7d91 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.17.0-rc1 + 4.17.0-rc2 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index 2f89586b..0da0c71f 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.17.0-rc1 + 4.17.0-rc2 redis-wrapper 3.1.1 diff --git a/testing/.github/CODEOWNERS b/testing/.github/CODEOWNERS deleted file mode 100644 index 9e319810..00000000 --- a/testing/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @splitio/sdk diff --git a/testing/.github/linter/checkstyle-suppressions.xml b/testing/.github/linter/checkstyle-suppressions.xml deleted file mode 100644 index 81d23539..00000000 --- a/testing/.github/linter/checkstyle-suppressions.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/testing/.github/linter/google-java-style.xml b/testing/.github/linter/google-java-style.xml deleted file mode 100644 index e885305e..00000000 --- a/testing/.github/linter/google-java-style.xml +++ /dev/null @@ -1,380 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/testing/pom.xml b/testing/pom.xml index 98f04d55..f7316b7b 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -5,11 +5,11 @@ io.split.client java-client-parent - 4.16.0 + 4.17.0-rc2 java-client-testing jar - 4.17.0-rc1 + 4.17.0-rc2 Java Client For Testing Testing suite for Java SDK for Split From 21d43befda766411265040bd36ae3d86a8dbd1d2 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 1 Jul 2025 11:41:13 -0700 Subject: [PATCH 15/30] polish --- client/src/main/java/io/split/client/SplitFactoryImpl.java | 2 +- client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index e1a11dcf..80f848c4 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -597,7 +597,7 @@ private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitCli return httpClientbuilder.build(); } - private static SSLContext buildSSLContext(SplitClientConfig config) throws IOException { + private static SSLContext buildSSLContext(SplitClientConfig config) throws IOException, NullPointerException { SSLContext sslContext; if (config.proxyMTLSAuth() != null) { _log.debug("Proxy setup using mTLS"); diff --git a/client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java b/client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java index ddd59696..5cca5abd 100644 --- a/client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java +++ b/client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java @@ -20,10 +20,7 @@ public static ProxyMTLSAuth.Builder builder() { public static class Builder { private String _p12File; private String _p12FilePassKey; - - public Builder() { - } - + public ProxyMTLSAuth.Builder proxyP12File(String p12File) { _p12File = p12File; return this; From d9e2bceafb11128027fca0752b1a3e8728c03d5e Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 1 Jul 2025 11:51:31 -0700 Subject: [PATCH 16/30] polish --- client/src/main/java/io/split/client/SplitFactoryImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 80f848c4..f6d932a2 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -614,7 +614,11 @@ private static SSLContext buildSSLContext(SplitClientConfig config) throws IOExc _log.warn("Ignoring p12 mTLS config and switching to default context"); sslContext = SSLContexts.createSystemDefault(); } finally { - keystoreStream.close(); + try { + keystoreStream.close(); + } catch (NullPointerException e) { + _log.error("Exception caught while closing file stream handler: ", e); + } } } else { sslContext = SSLContexts.createSystemDefault(); From 2113b7c00726312015faabd524e261787a6b6c1a Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Tue, 1 Jul 2025 12:10:18 -0700 Subject: [PATCH 17/30] polish --- client/src/main/java/io/split/client/SplitFactoryImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index f6d932a2..6e9d9913 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -614,10 +614,8 @@ private static SSLContext buildSSLContext(SplitClientConfig config) throws IOExc _log.warn("Ignoring p12 mTLS config and switching to default context"); sslContext = SSLContexts.createSystemDefault(); } finally { - try { + if (keystoreStream != null) { keystoreStream.close(); - } catch (NullPointerException e) { - _log.error("Exception caught while closing file stream handler: ", e); } } } else { From a5e4dc183c2c68b47d9387c8284263d47ca80c68 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Wed, 16 Jul 2025 16:46:46 -0700 Subject: [PATCH 18/30] Added new proxy config params --- client/pom.xml | 4 +- .../client/HttpClientDynamicCredentials.java | 9 +- .../client/ProxyCredentialsProvider.java | 10 -- .../io/split/client/SplitClientConfig.java | 95 ++++-------- .../io/split/client/SplitFactoryImpl.java | 51 +++++-- .../client/dtos/BasicCredentialsProvider.java | 7 + .../dtos/BearerCredentialsProvider.java | 6 + .../split/client/dtos/ProxyConfiguration.java | 57 +++++++ .../client/dtos/ProxyCredentialsProvider.java | 4 + .../io/split/client/dtos/ProxyMTLSAuth.java | 38 ----- .../split/client/SplitClientConfigTest.java | 139 +++++++----------- .../io/split/client/SplitFactoryImplTest.java | 71 ++++++--- okhttp-modules/pom.xml | 4 +- pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- testing/pom.xml | 2 +- 17 files changed, 264 insertions(+), 239 deletions(-) delete mode 100644 client/src/main/java/io/split/client/ProxyCredentialsProvider.java create mode 100644 client/src/main/java/io/split/client/dtos/BasicCredentialsProvider.java create mode 100644 client/src/main/java/io/split/client/dtos/BearerCredentialsProvider.java create mode 100644 client/src/main/java/io/split/client/dtos/ProxyConfiguration.java create mode 100644 client/src/main/java/io/split/client/dtos/ProxyCredentialsProvider.java delete mode 100644 client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java diff --git a/client/pom.xml b/client/pom.xml index 5310cfea..88ad8875 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,9 +5,9 @@ io.split.client java-client-parent - 4.17.0-rc2 + 4.17.0-rc3 - 4.17.0-rc2 + 4.17.0-rc3 java-client jar Java Client diff --git a/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java b/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java index 01a32362..ebcbe667 100644 --- a/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java +++ b/client/src/main/java/io/split/client/HttpClientDynamicCredentials.java @@ -1,5 +1,6 @@ package io.split.client; +import io.split.client.dtos.BearerCredentialsProvider; import org.apache.hc.client5.http.auth.AuthScope; import org.apache.hc.client5.http.auth.BearerToken; import org.apache.hc.client5.http.auth.Credentials; @@ -7,10 +8,10 @@ class HttpClientDynamicCredentials implements org.apache.hc.client5.http.auth.CredentialsProvider { - private final ProxyCredentialsProvider _proxyCredentialsProvider; + private final BearerCredentialsProvider _bearerCredentialsProvider; - public HttpClientDynamicCredentials (ProxyCredentialsProvider proxyCredentialsProvider) { - _proxyCredentialsProvider = proxyCredentialsProvider; + public HttpClientDynamicCredentials (BearerCredentialsProvider bearerCredentialsProvider) { + _bearerCredentialsProvider = bearerCredentialsProvider; } @Override @@ -18,7 +19,7 @@ public Credentials getCredentials(AuthScope authScope, HttpContext context) { // This Provider is invoked every time a request is made. // This should invoke a user-custom provider responsible for: - return new BearerToken(_proxyCredentialsProvider.getJwtToken()); + return new BearerToken(_bearerCredentialsProvider.getToken()); } } diff --git a/client/src/main/java/io/split/client/ProxyCredentialsProvider.java b/client/src/main/java/io/split/client/ProxyCredentialsProvider.java deleted file mode 100644 index 6fb595bc..00000000 --- a/client/src/main/java/io/split/client/ProxyCredentialsProvider.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.split.client; - -public interface ProxyCredentialsProvider -{ - /** - * Get the additional headers needed for all http operations - * @return HashMap of addition headers - */ - String getJwtToken(); -} diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index d314baa7..eb612951 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -1,6 +1,6 @@ package io.split.client; -import io.split.client.dtos.ProxyMTLSAuth; +import io.split.client.dtos.ProxyConfiguration; import io.split.client.impressions.ImpressionListener; import io.split.client.impressions.ImpressionsManager; import io.split.client.utils.FileTypeEnum; @@ -91,11 +91,10 @@ private HttpScheme() { private final ThreadFactory _threadFactory; // Proxy configs + private final ProxyConfiguration _proxyConfiguration; private final HttpHost _proxy; private final String _proxyUsername; private final String _proxyPassword; - private final ProxyCredentialsProvider _proxyCredentialsProvider; - private final ProxyMTLSAuth _proxyMtlsAuth; // To be set during startup public static String splitSdkVersion; @@ -129,8 +128,7 @@ private SplitClientConfig(String endpoint, HttpHost proxy, String proxyUsername, String proxyPassword, - ProxyCredentialsProvider proxyCredentialsProvider, - ProxyMTLSAuth proxyMtlsAuth, + ProxyConfiguration proxyConfiguration, int eventsQueueSize, long eventSendIntervalInMillis, int maxStringLength, @@ -184,8 +182,7 @@ private SplitClientConfig(String endpoint, _proxy = proxy; _proxyUsername = proxyUsername; _proxyPassword = proxyPassword; - _proxyCredentialsProvider = proxyCredentialsProvider; - _proxyMtlsAuth = proxyMtlsAuth; + _proxyConfiguration = proxyConfiguration; _eventsQueueSize = eventsQueueSize; _eventSendIntervalInMillis = eventSendIntervalInMillis; _maxStringLength = maxStringLength; @@ -317,12 +314,8 @@ public String proxyPassword() { return _proxyPassword; } - public ProxyCredentialsProvider proxyCredentialsProvider() { - return _proxyCredentialsProvider; - } - - public ProxyMTLSAuth proxyMTLSAuth() { - return _proxyMtlsAuth; + public ProxyConfiguration proxyConfiguration() { + return _proxyConfiguration; } public long eventSendIntervalInMillis() { @@ -463,11 +456,9 @@ public static final class Builder { private int _waitBeforeShutdown = 5000; private String _proxyHost = "localhost"; private int _proxyPort = -1; - private String _proxyScheme = HttpScheme.HTTP; private String _proxyUsername; private String _proxyPassword; - private ProxyCredentialsProvider _proxyCredentialsProvider; - private ProxyMTLSAuth _proxyMtlsAuth; + private ProxyConfiguration _proxyConfiguration; private int _eventsQueueSize = 500; private long _eventSendIntervalInMillis = 30 * (long)1000; private int _maxStringLength = 250; @@ -760,10 +751,14 @@ public Builder waitBeforeShutdown(int waitTime) { /** * The host location of the proxy. Default is localhost. + * @deprecated + * This method is deprecated. + *

Use {@link ProxyConfiguration)} instead. * * @param proxyHost location of the proxy * @return this builder */ + @Deprecated public Builder proxyHost(String proxyHost) { _proxyHost = proxyHost; return this; @@ -771,32 +766,29 @@ public Builder proxyHost(String proxyHost) { /** * The port of the proxy. Default is -1. + * @deprecated + * This method is deprecated. + *

Use {@link ProxyConfiguration)} instead. * * @param proxyPort port for the proxy * @return this builder */ + @Deprecated public Builder proxyPort(int proxyPort) { _proxyPort = proxyPort; return this; } - /** - * The http scheme of the proxy. Default is http. - * - * @param proxyScheme protocol for the proxy - * @return this builder - */ - public Builder proxyScheme(String proxyScheme) { - _proxyScheme = proxyScheme; - return this; - } - /** * Set the username for authentication against the proxy (if proxy settings are enabled). (Optional). + * @deprecated + * This method is deprecated. + *

Use {@link ProxyConfiguration)} instead. * * @param proxyUsername * @return this builder */ + @Deprecated public Builder proxyUsername(String proxyUsername) { _proxyUsername = proxyUsername; return this; @@ -813,25 +805,14 @@ public Builder proxyPassword(String proxyPassword) { return this; } - /** - * Set the token for authentication against the proxy (if proxy settings are enabled). (Optional). - * - * @param proxyCredentialsProvider - * @return this builder - */ - public Builder proxyCredentialsProvider(ProxyCredentialsProvider proxyCredentialsProvider) { - _proxyCredentialsProvider = proxyCredentialsProvider; - return this; - } - /** * Set the mtls authentication against the proxy (if proxy settings are enabled). (Optional). * - * @param proxyMtlsAuth + * @param proxyConfiguration * @return this builder */ - public Builder proxyMtlsAuth(ProxyMTLSAuth proxyMtlsAuth) { - _proxyMtlsAuth = proxyMtlsAuth; + public Builder proxyConfiguration(ProxyConfiguration proxyConfiguration) { + _proxyConfiguration = proxyConfiguration; return this; } @@ -847,7 +828,7 @@ public Builder disableDestroyOnShutDown() { HttpHost proxy() { if (_proxyPort != -1) { - return new HttpHost(_proxyScheme, _proxyHost, _proxyPort); + return new HttpHost(_proxyHost, _proxyPort); } // Default is no proxy. return null; @@ -986,7 +967,7 @@ public Builder operationMode(OperationMode mode) { /** * - * @param storage mode + * @param mode * @return this builder */ public Builder storageMode(StorageMode mode) { @@ -1156,31 +1137,16 @@ private void verifyAlternativeClient() { } private void verifyProxy() { - if (_proxyPort == -1) { + if (_proxyConfiguration == null) return; - } - if (!(_proxyScheme.equals(HttpScheme.HTTP) || _proxyScheme.equals(HttpScheme.HTTPS))) { + if (!(_proxyConfiguration.getHost().getSchemeName().equals(HttpScheme.HTTP) || + _proxyConfiguration.getHost().getSchemeName().equals(HttpScheme.HTTPS))) { throw new IllegalArgumentException("Proxy scheme must be either http or https."); } - if (_proxyUsername == null && _proxyCredentialsProvider == null && _proxyMtlsAuth == null) { - return; - } - - if (_proxyUsername != null && _proxyCredentialsProvider != null) { - throw new IllegalArgumentException("Proxy user and Proxy token params are updated, set only one param."); - } - - if (_proxyUsername != null && _proxyMtlsAuth != null) { - throw new IllegalArgumentException("Proxy user and Proxy mTLS params are updated, set only one param."); - } - - if (_proxyCredentialsProvider != null && _proxyMtlsAuth != null) { - throw new IllegalArgumentException("Proxy token and Proxy mTLS params are updated, set only one param."); - } - - if (_proxyMtlsAuth != null && (_proxyMtlsAuth.getP12File() == null || _proxyMtlsAuth.getP12FilePassKey() == null)) { + if ((_proxyConfiguration.getP12File() != null && _proxyConfiguration.getPassKey() == null) || + (_proxyConfiguration.getP12File() == null && _proxyConfiguration.getPassKey() != null)) { throw new IllegalArgumentException("Proxy mTLS must have p12 file path and name, and pass phrase."); } } @@ -1224,8 +1190,7 @@ public SplitClientConfig build() { proxy(), _proxyUsername, _proxyPassword, - _proxyCredentialsProvider, - _proxyMtlsAuth, + _proxyConfiguration, _eventsQueueSize, _eventSendIntervalInMillis, _maxStringLength, diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 6e9d9913..95a84cd7 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -1,6 +1,7 @@ package io.split.client; import com.google.common.io.Files; +import io.split.client.dtos.BearerCredentialsProvider; import io.split.client.dtos.Metadata; import io.split.client.events.EventsSender; import io.split.client.events.EventsStorage; @@ -105,6 +106,7 @@ import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner; import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder; +import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.http.ssl.TLS; import org.apache.hc.core5.ssl.SSLContexts; @@ -551,7 +553,7 @@ protected static SplitHttpClient buildSplitHttpClient(String apiToken, SplitClie .addResponseInterceptorLast((new GzipDecoderResponseInterceptor())); // Set up proxy is it exists - if (config.proxy() != null) { + if (config.proxy() != null || config.proxyConfiguration() != null) { httpClientbuilder = setupProxy(httpClientbuilder, config); } @@ -590,7 +592,7 @@ private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitCli .addRequestInterceptorLast(ClientKeyInterceptorFilter.instance(apiToken)); // Set up proxy is it exists - if (config.proxy() != null) { + if (config.proxy() != null || config.proxyConfiguration() != null) { httpClientbuilder = setupProxy(httpClientbuilder, config); } @@ -599,15 +601,15 @@ private static CloseableHttpClient buildSSEdHttpClient(String apiToken, SplitCli private static SSLContext buildSSLContext(SplitClientConfig config) throws IOException, NullPointerException { SSLContext sslContext; - if (config.proxyMTLSAuth() != null) { + if (config.proxyConfiguration() != null && config.proxyConfiguration().getP12File() != null) { _log.debug("Proxy setup using mTLS"); InputStream keystoreStream = null; try { KeyStore keyStore = KeyStore.getInstance("PKCS12"); - keystoreStream = java.nio.file.Files.newInputStream(Paths.get(config.proxyMTLSAuth().getP12File())); - keyStore.load(keystoreStream, config.proxyMTLSAuth().getP12FilePassKey().toCharArray()); + keystoreStream = java.nio.file.Files.newInputStream(Paths.get(config.proxyConfiguration().getP12File())); + keyStore.load(keystoreStream, config.proxyConfiguration().getPassKey().toCharArray()); sslContext = SSLContexts.custom() - .loadKeyMaterial(keyStore, config.proxyMTLSAuth().getP12FilePassKey().toCharArray()) + .loadKeyMaterial(keyStore, config.proxyConfiguration().getPassKey().toCharArray()) .build(); } catch (Exception e) { _log.error("Exception caught while processing p12 file for Proxy mTLS auth: ", e); @@ -626,22 +628,43 @@ private static SSLContext buildSSLContext(SplitClientConfig config) throws IOExc private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, SplitClientConfig config) { _log.info("Initializing Split SDK with proxy settings"); - DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(config.proxy()); + HttpHost proxyHost; + if (config.proxyConfiguration() != null && config.proxyConfiguration().getHost() != null) { + proxyHost = config.proxyConfiguration().getHost(); + } else { + proxyHost = config.proxy(); + } + DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxyHost); httpClientbuilder.setRoutePlanner(routePlanner); - if (config.proxyUsername() != null && config.proxyPassword() != null) { + if ((config.proxyUsername() != null && config.proxyPassword() != null) || + (config.proxyConfiguration() != null && config.proxyConfiguration().getProxyCredentialsProvider() != null && + config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BasicCredentialsProvider)) { _log.debug("Proxy setup using credentials"); + String userName; + String password; + if (config.proxyUsername() != null && config.proxyPassword() != null) { + userName = config.proxyUsername(); + password = config.proxyPassword(); + } else { + io.split.client.dtos.BasicCredentialsProvider basicAuth = + (io.split.client.dtos.BasicCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider(); + userName = basicAuth.getUsername(); + password = basicAuth.getPassword(); + } BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); - AuthScope siteScope = new AuthScope(config.proxy().getHostName(), config.proxy().getPort()); - Credentials siteCreds = new UsernamePasswordCredentials(config.proxyUsername(), - config.proxyPassword().toCharArray()); + AuthScope siteScope = new AuthScope(proxyHost.getHostName(), proxyHost.getPort()); + Credentials siteCreds = new UsernamePasswordCredentials(userName, + password.toCharArray()); credsProvider.setCredentials(siteScope, siteCreds); httpClientbuilder.setDefaultCredentialsProvider(credsProvider); } - if (config.proxyCredentialsProvider() != null) { - _log.debug("Proxy setup using token"); - httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials(config.proxyCredentialsProvider())); + if (config.proxyConfiguration() != null && + config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BearerCredentialsProvider) { + _log.debug("Proxy setup using Bearer token"); + httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials( + (BearerCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider())); } return httpClientbuilder; diff --git a/client/src/main/java/io/split/client/dtos/BasicCredentialsProvider.java b/client/src/main/java/io/split/client/dtos/BasicCredentialsProvider.java new file mode 100644 index 00000000..b77c9f59 --- /dev/null +++ b/client/src/main/java/io/split/client/dtos/BasicCredentialsProvider.java @@ -0,0 +1,7 @@ +package io.split.client.dtos; + +public interface BasicCredentialsProvider extends ProxyCredentialsProvider +{ + String getUsername(); + String getPassword(); +} diff --git a/client/src/main/java/io/split/client/dtos/BearerCredentialsProvider.java b/client/src/main/java/io/split/client/dtos/BearerCredentialsProvider.java new file mode 100644 index 00000000..d4e98c5f --- /dev/null +++ b/client/src/main/java/io/split/client/dtos/BearerCredentialsProvider.java @@ -0,0 +1,6 @@ +package io.split.client.dtos; + +public interface BearerCredentialsProvider extends ProxyCredentialsProvider +{ + String getToken(); +} diff --git a/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java b/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java new file mode 100644 index 00000000..f48a8c1c --- /dev/null +++ b/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java @@ -0,0 +1,57 @@ +package io.split.client.dtos; + +import org.apache.hc.core5.http.HttpHost; + +import java.net.URL; + +public class ProxyConfiguration { + private final HttpHost _proxyHost; + private ProxyCredentialsProvider _provider; + private final String _p12File; + private final String _passKey; + + private ProxyConfiguration(HttpHost proxyHost, + ProxyCredentialsProvider proxyCredentialsProvider, + String p12File, String passKey) { + _proxyHost = proxyHost; + _p12File = p12File; + _passKey = passKey; + _provider = proxyCredentialsProvider; + } + + public HttpHost getHost() { return _proxyHost; } + public String getP12File() { return _p12File; } + public String getPassKey() { return _passKey; } + public ProxyCredentialsProvider getProxyCredentialsProvider() { return _provider; } + + public static ProxyConfiguration.Builder builder() { + return new ProxyConfiguration.Builder(); + } + + public static class Builder { + private ProxyCredentialsProvider _provider; + private HttpHost _proxyHost; + private String _p12File; + private String _passKey; + + public ProxyConfiguration.Builder credentialsProvider(ProxyCredentialsProvider provider) { + _provider = provider; + return this; + } + + public ProxyConfiguration.Builder url(URL url) { + _proxyHost = new HttpHost(url.getProtocol(), url.getHost(), url.getPort()); + return this; + } + + public ProxyConfiguration.Builder mtls(String p12File, String passKey) { + _passKey = passKey; + _p12File = p12File; + return this; + } + + public ProxyConfiguration build() { + return new ProxyConfiguration(_proxyHost, _provider, _p12File, _passKey); + } + } +} \ No newline at end of file diff --git a/client/src/main/java/io/split/client/dtos/ProxyCredentialsProvider.java b/client/src/main/java/io/split/client/dtos/ProxyCredentialsProvider.java new file mode 100644 index 00000000..e1653d5f --- /dev/null +++ b/client/src/main/java/io/split/client/dtos/ProxyCredentialsProvider.java @@ -0,0 +1,4 @@ +package io.split.client.dtos; + +public interface ProxyCredentialsProvider +{} diff --git a/client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java b/client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java deleted file mode 100644 index 5cca5abd..00000000 --- a/client/src/main/java/io/split/client/dtos/ProxyMTLSAuth.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.split.client.dtos; - -public class ProxyMTLSAuth { - private final String _proxyP12File; - private final String _proxyP12FilePassKey; - - private ProxyMTLSAuth(String proxyP12File, String proxyP12FilePassKey) { - _proxyP12File = proxyP12File; - _proxyP12FilePassKey = proxyP12FilePassKey; - } - - public String getP12File() { return _proxyP12File; } - - public String getP12FilePassKey() { return _proxyP12FilePassKey; } - - public static ProxyMTLSAuth.Builder builder() { - return new ProxyMTLSAuth.Builder(); - } - - public static class Builder { - private String _p12File; - private String _p12FilePassKey; - - public ProxyMTLSAuth.Builder proxyP12File(String p12File) { - _p12File = p12File; - return this; - } - - public ProxyMTLSAuth.Builder proxyP12FilePassKey(String p12FilePassKey) { - _p12FilePassKey = p12FilePassKey; - return this; - } - - public ProxyMTLSAuth build() { - return new ProxyMTLSAuth(_p12File, _p12FilePassKey); - } - } -} \ No newline at end of file diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index 81ad9913..ce25746a 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -1,7 +1,9 @@ package io.split.client; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import io.split.client.dtos.ProxyMTLSAuth; +import io.split.client.dtos.BasicCredentialsProvider; +import io.split.client.dtos.BearerCredentialsProvider; +import io.split.client.dtos.ProxyConfiguration; import io.split.client.impressions.Impression; import io.split.client.impressions.ImpressionListener; import io.split.client.impressions.ImpressionsManager; @@ -11,6 +13,8 @@ import org.junit.Test; import org.mockito.Mockito; +import java.net.MalformedURLException; +import java.net.URL; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -256,116 +260,87 @@ public Map> getHeaderOverrides(RequestContext context) { } @Test - public void checkProxyParams() { + public void checkProxyParams() throws MalformedURLException { SplitClientConfig config = SplitClientConfig.builder() - .proxyHost("proxy-host") - .proxyPort(8888).build(); - Assert.assertEquals("proxy-host", config.proxy().getHostName()); - Assert.assertEquals(8888, config.proxy().getPort()); + .proxyConfiguration(new ProxyConfiguration.Builder() + .url(new URL("https://proxy-host:8888")) + .build()) + .build(); + Assert.assertEquals("proxy-host", config.proxyConfiguration().getHost().getHostName()); + Assert.assertEquals(8888, config.proxyConfiguration().getHost().getPort()); + Assert.assertEquals("https", config.proxyConfiguration().getHost().getSchemeName()); config = SplitClientConfig.builder() - .proxyHost("proxy-host") - .proxyPort(8888) - .proxyScheme(SplitClientConfig.HttpScheme.HTTPS) - .proxyUsername("user") - .proxyPassword("pass") + .proxyConfiguration(new ProxyConfiguration.Builder() + .url(new URL("https://proxy-host:888")) + .credentialsProvider(new io.split.client.dtos.BasicCredentialsProvider() { + @Override + public String getUsername() { + return "user"; + } + + @Override + public String getPassword() { + return "pass"; + } + }) + .build()) .build(); - Assert.assertEquals("user", config.proxyUsername()); - Assert.assertEquals("pass", config.proxyPassword()); + io.split.client.dtos.BasicCredentialsProvider basicAuth = (io.split.client.dtos.BasicCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider(); + Assert.assertEquals("user", basicAuth.getUsername()); + Assert.assertEquals("pass", basicAuth.getPassword()); - ProxyCredentialsProvider proxyCredentialsProvider = new ProxyCredentialsProvider() { + io.split.client.dtos.BearerCredentialsProvider bearerCredentialsProvider = new io.split.client.dtos.BearerCredentialsProvider() { @Override - public String getJwtToken() { + public String getToken() { return "my-token"; } }; config = SplitClientConfig.builder() - .proxyHost("proxy-host") - .proxyPort(8888) - .proxyCredentialsProvider(proxyCredentialsProvider) + .proxyConfiguration(new ProxyConfiguration.Builder() + .url(new URL("https://proxy-host:888")) + .credentialsProvider(bearerCredentialsProvider) + .build()) .build(); - Assert.assertEquals(proxyCredentialsProvider, config.proxyCredentialsProvider()); + Assert.assertEquals(bearerCredentialsProvider, config.proxyConfiguration().getProxyCredentialsProvider()); config = SplitClientConfig.builder() - .proxyHost("proxy-host") - .proxyPort(8888) - .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build()) - .build(); - Assert.assertEquals("path/to/file", config.proxyMTLSAuth().getP12File()); - Assert.assertEquals("pass-key", config.proxyMTLSAuth().getP12FilePassKey()); - } - - @Test(expected = IllegalArgumentException.class) - public void cannotUseInvalidHttpScheme() { - SplitClientConfig.builder() - .proxyHost("proxy-host") - .proxyPort(8888) - .proxyScheme("ftp") - .build(); - } - - @Test(expected = IllegalArgumentException.class) - public void cannotUseProxyTokenAndProxyUsername() { - ProxyCredentialsProvider proxyCredentialsProvider = new ProxyCredentialsProvider() { - @Override - public String getJwtToken() { - return "my-token"; - } - }; - - SplitClientConfig.builder() - .proxyHost("proxy-host") - .proxyPort(8888) - .proxyUsername("user") - .proxyPassword("pass") - .proxyCredentialsProvider(proxyCredentialsProvider) - .build(); - } - - @Test(expected = IllegalArgumentException.class) - public void cannotUseProxyUserAndProxyMtls() { - SplitClientConfig.builder() - .proxyHost("proxy-host") - .proxyPort(8888) - .proxyUsername("user") - .proxyPassword("pass") - .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build()) + .proxyConfiguration(new ProxyConfiguration.Builder() + .url(new URL("https://proxy-host:888")) + .mtls("path/to/file", "pass-key") + .build()) .build(); + Assert.assertEquals("path/to/file", config.proxyConfiguration().getP12File()); + Assert.assertEquals("pass-key", config.proxyConfiguration().getPassKey()); } @Test(expected = IllegalArgumentException.class) - public void cannotUseProxyTokenAndProxyMtls() { - ProxyCredentialsProvider proxyCredentialsProvider = new ProxyCredentialsProvider() { - @Override - public String getJwtToken() { - return "my-token"; - } - }; - + public void cannotUseInvalidHttpScheme() throws MalformedURLException { SplitClientConfig.builder() - .proxyHost("proxy-host") - .proxyPort(8888) - .proxyCredentialsProvider(proxyCredentialsProvider) - .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").proxyP12FilePassKey("pass-key").build()) + .proxyConfiguration(new ProxyConfiguration.Builder() + .url(new URL("ftp://proxy-host:888")) + .build()) .build(); } @Test(expected = IllegalArgumentException.class) - public void mustUseP12FileWithProxyMtls() { + public void mustUseP12FileWithProxyMtls() throws MalformedURLException { SplitClientConfig.builder() - .proxyHost("proxy-host") - .proxyPort(8888) - .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12FilePassKey("pass-key").build()) + .proxyConfiguration(new ProxyConfiguration.Builder() + .url(new URL("https://proxy-host:888")) + .mtls(null, "pass-key") + .build()) .build(); } @Test(expected = IllegalArgumentException.class) - public void mustUseP12PassKeyWithProxyMtls() { + public void mustUseP12PassKeyWithProxyMtls() throws MalformedURLException { SplitClientConfig.builder() - .proxyHost("proxy-host") - .proxyPort(8888) - .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("path/to/file").build()) + .proxyConfiguration(new ProxyConfiguration.Builder() + .url(new URL("https://proxy-host:888")) + .mtls("path/to/file", null) + .build()) .build(); } } \ No newline at end of file diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index 1214b246..a8b3f10c 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -1,6 +1,7 @@ package io.split.client; -import io.split.client.dtos.ProxyMTLSAuth; +import io.split.client.dtos.BearerCredentialsProvider; +import io.split.client.dtos.ProxyConfiguration; import io.split.client.impressions.ImpressionsManager; import io.split.client.utils.FileTypeEnum; import io.split.integrations.IntegrationsConfig; @@ -33,6 +34,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URISyntaxException; +import java.net.URL; import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -97,8 +99,40 @@ public void testFactoryInstantiationIntegrationsConfig() throws Exception { assertNotNull(splitFactory.manager()); } + @Test + public void testFactoryInstantiationWithLegacyProxy() throws Exception { + SplitClientConfig splitClientConfig = SplitClientConfig.builder() + .enableDebug() + .impressionsMode(ImpressionsManager.Mode.DEBUG) + .impressionsRefreshRate(1) + .endpoint(ENDPOINT, EVENTS_ENDPOINT) + .telemetryURL(SplitClientConfig.TELEMETRY_ENDPOINT) + .authServiceURL(AUTH_SERVICE) + .setBlockUntilReadyTimeout(1000) + .proxyPort(8888) + .proxyHost("proxy-host") + .proxyUsername("user") + .proxyPassword("pass") + .build(); + SplitFactoryImpl splitFactory = new SplitFactoryImpl(API_KEY, splitClientConfig); + assertNotNull(splitFactory.client()); + + splitFactory.destroy(); + } + @Test public void testFactoryInstantiationWithProxyCredentials() throws Exception { + class MyBearerCredentialsProvider implements io.split.client.dtos.BasicCredentialsProvider { + @Override + public String getUsername() { + return "test"; + } + @Override + public String getPassword() { + return "password"; + } + }; + SplitClientConfig splitClientConfig = SplitClientConfig.builder() .enableDebug() .impressionsMode(ImpressionsManager.Mode.DEBUG) @@ -107,10 +141,10 @@ public void testFactoryInstantiationWithProxyCredentials() throws Exception { .telemetryURL(SplitClientConfig.TELEMETRY_ENDPOINT) .authServiceURL(AUTH_SERVICE) .setBlockUntilReadyTimeout(1000) - .proxyPort(6060) - .proxyUsername("test") - .proxyPassword("password") - .proxyHost(ENDPOINT) + .proxyConfiguration(ProxyConfiguration.builder() + .url(new URL("http://proxy-name:6060")) + .credentialsProvider(new MyBearerCredentialsProvider()) + .build()) .build(); SplitFactoryImpl splitFactory = new SplitFactoryImpl(API_KEY, splitClientConfig); assertNotNull(splitFactory.client()); @@ -133,7 +167,7 @@ public void testFactoryInstantiationWithProxyCredentials() throws Exception { HttpHost proxy = (HttpHost) proxyField.get(routePlanner); Assert.assertEquals("http", proxy.getSchemeName()); - Assert.assertEquals(ENDPOINT, proxy.getHostName()); + Assert.assertEquals("proxy-name", proxy.getHostName()); Assert.assertEquals(6060, proxy.getPort()); Field credentialsProviderField = InternalHttp.getDeclaredField("credentialsProvider"); @@ -152,9 +186,9 @@ public void testFactoryInstantiationWithProxyCredentials() throws Exception { @Test public void testFactoryInstantiationWithProxyToken() throws Exception { - class MyProxyCredentialsProvider implements ProxyCredentialsProvider { + class MyBearerCredentialsProvider implements io.split.client.dtos.BearerCredentialsProvider { @Override - public String getJwtToken() { + public String getToken() { return "123456789"; } }; @@ -167,9 +201,10 @@ public String getJwtToken() { .telemetryURL(SplitClientConfig.TELEMETRY_ENDPOINT) .authServiceURL(AUTH_SERVICE) .setBlockUntilReadyTimeout(1000) - .proxyPort(6060) - .proxyCredentialsProvider(new MyProxyCredentialsProvider()) - .proxyHost(ENDPOINT) + .proxyConfiguration(ProxyConfiguration.builder() + .url(new URL("http://proxy-name:6060")) + .credentialsProvider(new MyBearerCredentialsProvider()) + .build()) .build(); SplitFactoryImpl splitFactory2 = new SplitFactoryImpl(API_KEY, splitClientConfig); assertNotNull(splitFactory2.client()); @@ -187,11 +222,11 @@ public String getJwtToken() { credentialsProviderField2.setAccessible(true); HttpClientDynamicCredentials credentialsProvider2 = (HttpClientDynamicCredentials) credentialsProviderField2.get(InternalHttp2.cast(httpClientField2.get(client2))); - Field proxyRuntimeField = HttpClientDynamicCredentials.class.getDeclaredField("_proxyCredentialsProvider"); + Field proxyRuntimeField = HttpClientDynamicCredentials.class.getDeclaredField("_bearerCredentialsProvider"); proxyRuntimeField.setAccessible(true); - MyProxyCredentialsProvider proxyRuntime = (MyProxyCredentialsProvider) proxyRuntimeField.get(credentialsProvider2); + MyBearerCredentialsProvider proxyRuntime = (MyBearerCredentialsProvider) proxyRuntimeField.get(credentialsProvider2); - assertNotNull("123456789", proxyRuntime.getJwtToken()); + assertNotNull("123456789", proxyRuntime.getToken()); splitFactory2.destroy(); } @@ -206,10 +241,10 @@ public void testFactoryInstantiationWithProxyMtls() throws Exception { .telemetryURL(SplitClientConfig.TELEMETRY_ENDPOINT) .authServiceURL(AUTH_SERVICE) .setBlockUntilReadyTimeout(1000) - .proxyPort(6060) - .proxyScheme("https") - .proxyMtlsAuth(new ProxyMTLSAuth.Builder().proxyP12File("src/test/resources/keyStore.p12").proxyP12FilePassKey("split").build()) - .proxyHost(ENDPOINT) + .proxyConfiguration(ProxyConfiguration.builder() + .url(new URL("http://proxy-name:6060")) + .mtls("src/test/resources/keyStore.p12", "split") + .build()) .build(); SplitFactoryImpl splitFactory3 = new SplitFactoryImpl(API_KEY, splitClientConfig); assertNotNull(splitFactory3.client()); diff --git a/okhttp-modules/pom.xml b/okhttp-modules/pom.xml index ff0bac2e..0dfc2529 100644 --- a/okhttp-modules/pom.xml +++ b/okhttp-modules/pom.xml @@ -5,10 +5,10 @@ java-client-parent io.split.client - 4.17.0-rc2 + 4.17.0-rc3 4.0.0 - 4.17.0-rc2 + 4.17.0-rc3 okhttp-modules jar http-modules diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index 0353d0c5..3a908213 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.17.0-rc2 + 4.17.0-rc3 2.1.0 diff --git a/pom.xml b/pom.xml index cabb7d91..6f01df05 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.17.0-rc2 + 4.17.0-rc3 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index 0da0c71f..b65a1984 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.17.0-rc2 + 4.17.0-rc3 redis-wrapper 3.1.1 diff --git a/testing/pom.xml b/testing/pom.xml index f7316b7b..f32fa9b3 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.17.0-rc2 + 4.17.0-rc3 java-client-testing jar From 741e23d167c465b72a92f5329b4a0c1959394c1e Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Wed, 16 Jul 2025 16:51:20 -0700 Subject: [PATCH 19/30] revert version back --- client/pom.xml | 4 ++-- okhttp-modules/pom.xml | 4 ++-- pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- testing/pom.xml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/pom.xml b/client/pom.xml index 88ad8875..5310cfea 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,9 +5,9 @@ io.split.client java-client-parent - 4.17.0-rc3 + 4.17.0-rc2 - 4.17.0-rc3 + 4.17.0-rc2 java-client jar Java Client diff --git a/okhttp-modules/pom.xml b/okhttp-modules/pom.xml index 0dfc2529..ff0bac2e 100644 --- a/okhttp-modules/pom.xml +++ b/okhttp-modules/pom.xml @@ -5,10 +5,10 @@ java-client-parent io.split.client - 4.17.0-rc3 + 4.17.0-rc2 4.0.0 - 4.17.0-rc3 + 4.17.0-rc2 okhttp-modules jar http-modules diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index 3a908213..0353d0c5 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.17.0-rc3 + 4.17.0-rc2 2.1.0 diff --git a/pom.xml b/pom.xml index 6f01df05..cabb7d91 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.17.0-rc3 + 4.17.0-rc2 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index b65a1984..0da0c71f 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.17.0-rc3 + 4.17.0-rc2 redis-wrapper 3.1.1 diff --git a/testing/pom.xml b/testing/pom.xml index f32fa9b3..f7316b7b 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.17.0-rc3 + 4.17.0-rc2 java-client-testing jar From 9c11e854a69a5be68a4522af71ba424d6f9b3bc3 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Thu, 17 Jul 2025 11:56:08 -0700 Subject: [PATCH 20/30] Updated pom and proxy config --- .../io/split/client/dtos/ProxyConfiguration.java | 9 +++++++-- .../io/split/client/SplitClientConfigTest.java | 9 +++++++++ .../io/split/client/SplitFactoryImplTest.java | 1 - pom.xml | 16 ---------------- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java b/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java index f48a8c1c..049afb8d 100644 --- a/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java +++ b/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java @@ -2,6 +2,7 @@ import org.apache.hc.core5.http.HttpHost; +import java.net.MalformedURLException; import java.net.URL; public class ProxyConfiguration { @@ -39,8 +40,12 @@ public ProxyConfiguration.Builder credentialsProvider(ProxyCredentialsProvider p return this; } - public ProxyConfiguration.Builder url(URL url) { - _proxyHost = new HttpHost(url.getProtocol(), url.getHost(), url.getPort()); + public ProxyConfiguration.Builder url(URL url) throws MalformedURLException { + try { + _proxyHost = new HttpHost(url.getProtocol(), url.getHost(), url.getPort()); + } catch (Exception exc) { + throw new MalformedURLException("roxy configuration is ignored. The proxy `url` was not provided or is malformed"); + } return this; } diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index ce25746a..4f166a73 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -324,6 +324,15 @@ public void cannotUseInvalidHttpScheme() throws MalformedURLException { .build(); } + @Test(expected = MalformedURLException.class) + public void cannotUseInvalidUrl() throws MalformedURLException { + SplitClientConfig.builder() + .proxyConfiguration(new ProxyConfiguration.Builder() + .url(new URL("")) + .build()) + .build(); + } + @Test(expected = IllegalArgumentException.class) public void mustUseP12FileWithProxyMtls() throws MalformedURLException { SplitClientConfig.builder() diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index a8b3f10c..222ddc82 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -1,6 +1,5 @@ package io.split.client; -import io.split.client.dtos.BearerCredentialsProvider; import io.split.client.dtos.ProxyConfiguration; import io.split.client.impressions.ImpressionsManager; import io.split.client.utils.FileTypeEnum; diff --git a/pom.xml b/pom.xml index cabb7d91..b1c91c81 100644 --- a/pom.xml +++ b/pom.xml @@ -53,16 +53,8 @@ ossrh https://oss.sonatype.org/content/repositories/releases - - maven-all-virtual - https://splitio.jfrog.io/artifactory/maven-all-virtual - - - maven-all-virtual - https://splitio.jfrog.io/artifactory/maven-all-virtual - UTF-8 @@ -146,14 +138,6 @@ test - - maven-dev - https://splitio.jfrog.io/artifactory/maven-dev/ - - - maven-dev - https://splitio.jfrog.io/artifactory/maven-dev/ - From dfd9cfc47f220b3c49fbbb5e9661fffdc59c6df3 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Thu, 17 Jul 2025 11:59:04 -0700 Subject: [PATCH 21/30] removed empty element --- pom.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pom.xml b/pom.xml index b1c91c81..c2c595f0 100644 --- a/pom.xml +++ b/pom.xml @@ -137,8 +137,6 @@ test - - From b127c0eca661e83ab4f422be40087d0776b354b1 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany <41021307+chillaq@users.noreply.github.com> Date: Thu, 17 Jul 2025 12:12:57 -0700 Subject: [PATCH 22/30] Update ci.yml --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 721a6707..bff41c9d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,9 +59,9 @@ jobs: if: matrix.jdk == '8' && github.event_name == 'pull_request' && github.ref != 'refs/heads/master' && github.ref != 'refs/heads/development' run: mvn checkstyle::check - - name: Deploy - if: matrix.jdk == '8' && github.event_name == 'push' && github.ref != 'refs/heads/master' && github.ref != 'refs/heads/development' - run: mvn --batch-mode deploy -P test +# - name: Deploy +# if: matrix.jdk == '8' && github.event_name == 'push' && github.ref != 'refs/heads/master' && github.ref != 'refs/heads/development' +# run: mvn --batch-mode deploy -P test - name: SonarQube Scan (Push) if: matrix.jdk == '11' && github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/development') From 264f0842611528b8d949f1d213f0ba4ee1b94a4e Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Thu, 17 Jul 2025 12:40:45 -0700 Subject: [PATCH 23/30] Update SDK version to rc3 --- client/pom.xml | 4 ++-- okhttp-modules/pom.xml | 4 ++-- pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- testing/pom.xml | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/client/pom.xml b/client/pom.xml index 5310cfea..88ad8875 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,9 +5,9 @@ io.split.client java-client-parent - 4.17.0-rc2 + 4.17.0-rc3 - 4.17.0-rc2 + 4.17.0-rc3 java-client jar Java Client diff --git a/okhttp-modules/pom.xml b/okhttp-modules/pom.xml index ff0bac2e..0dfc2529 100644 --- a/okhttp-modules/pom.xml +++ b/okhttp-modules/pom.xml @@ -5,10 +5,10 @@ java-client-parent io.split.client - 4.17.0-rc2 + 4.17.0-rc3 4.0.0 - 4.17.0-rc2 + 4.17.0-rc3 okhttp-modules jar http-modules diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index 0353d0c5..3a908213 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.17.0-rc2 + 4.17.0-rc3 2.1.0 diff --git a/pom.xml b/pom.xml index c2c595f0..e8acb3c8 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.17.0-rc2 + 4.17.0-rc3 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index 0da0c71f..b65a1984 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.17.0-rc2 + 4.17.0-rc3 redis-wrapper 3.1.1 diff --git a/testing/pom.xml b/testing/pom.xml index f7316b7b..ee52481f 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -5,11 +5,11 @@ io.split.client java-client-parent - 4.17.0-rc2 + 4.17.0-rc3 java-client-testing jar - 4.17.0-rc2 + 4.17.0-rc3 Java Client For Testing Testing suite for Java SDK for Split From d30ef5a02f32bf445e0e8f674ae0a104d9cc47bb Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany <41021307+chillaq@users.noreply.github.com> Date: Thu, 17 Jul 2025 12:52:22 -0700 Subject: [PATCH 24/30] Update client/src/main/java/io/split/client/dtos/ProxyConfiguration.java Co-authored-by: Emiliano Sanchez --- .../src/main/java/io/split/client/dtos/ProxyConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java b/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java index 049afb8d..a3be9029 100644 --- a/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java +++ b/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java @@ -44,7 +44,7 @@ public ProxyConfiguration.Builder url(URL url) throws MalformedURLException { try { _proxyHost = new HttpHost(url.getProtocol(), url.getHost(), url.getPort()); } catch (Exception exc) { - throw new MalformedURLException("roxy configuration is ignored. The proxy `url` was not provided or is malformed"); + throw new MalformedURLException("Proxy configuration is ignored. The proxy `url` was not provided or is malformed"); } return this; } From 9bb8b29bfbd7a6c2976b4f17afa7c3c584a166dc Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Thu, 17 Jul 2025 13:01:25 -0700 Subject: [PATCH 25/30] Added check for missing url --- .../java/io/split/client/dtos/ProxyConfiguration.java | 5 ++++- .../test/java/io/split/client/SplitClientConfigTest.java | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java b/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java index 049afb8d..93d58c4c 100644 --- a/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java +++ b/client/src/main/java/io/split/client/dtos/ProxyConfiguration.java @@ -44,7 +44,7 @@ public ProxyConfiguration.Builder url(URL url) throws MalformedURLException { try { _proxyHost = new HttpHost(url.getProtocol(), url.getHost(), url.getPort()); } catch (Exception exc) { - throw new MalformedURLException("roxy configuration is ignored. The proxy `url` was not provided or is malformed"); + throw new MalformedURLException("Proxy configuration is invalid. The proxy `url` is malformed"); } return this; } @@ -56,6 +56,9 @@ public ProxyConfiguration.Builder mtls(String p12File, String passKey) { } public ProxyConfiguration build() { + if (_proxyHost == null) { + throw new IllegalArgumentException("Proxy configuration is invalid. The proxy `url` was not provided"); + } return new ProxyConfiguration(_proxyHost, _provider, _p12File, _passKey); } } diff --git a/client/src/test/java/io/split/client/SplitClientConfigTest.java b/client/src/test/java/io/split/client/SplitClientConfigTest.java index 4f166a73..8330f13a 100644 --- a/client/src/test/java/io/split/client/SplitClientConfigTest.java +++ b/client/src/test/java/io/split/client/SplitClientConfigTest.java @@ -333,6 +333,14 @@ public void cannotUseInvalidUrl() throws MalformedURLException { .build(); } + @Test(expected = IllegalArgumentException.class) + public void mustUseUrl() throws MalformedURLException { + SplitClientConfig.builder() + .proxyConfiguration(new ProxyConfiguration.Builder() + .build()) + .build(); + } + @Test(expected = IllegalArgumentException.class) public void mustUseP12FileWithProxyMtls() throws MalformedURLException { SplitClientConfig.builder() From bdad865882a9149bd0f13128276f04d2609f1e32 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Thu, 17 Jul 2025 13:18:27 -0700 Subject: [PATCH 26/30] polishing --- .../main/java/io/split/client/SplitFactoryImpl.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 95a84cd7..e3badac7 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -632,6 +632,7 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, if (config.proxyConfiguration() != null && config.proxyConfiguration().getHost() != null) { proxyHost = config.proxyConfiguration().getHost(); } else { + _log.warn("`proxyHost`, `proxyPort` configuration methods are deprecated. Please use `ProxyConfiguration` builder instead."); proxyHost = config.proxy(); } DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxyHost); @@ -643,14 +644,16 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, _log.debug("Proxy setup using credentials"); String userName; String password; - if (config.proxyUsername() != null && config.proxyPassword() != null) { - userName = config.proxyUsername(); - password = config.proxyPassword(); - } else { + if (config.proxyUsername() == null && config.proxyPassword() == null) { io.split.client.dtos.BasicCredentialsProvider basicAuth = (io.split.client.dtos.BasicCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider(); userName = basicAuth.getUsername(); password = basicAuth.getPassword(); + } else { + _log.warn("`proxyUsername` and `proxyPassword` configuration methods are deprecated. " + + "Please use `ProxyConfiguration` builder instead."); + userName = config.proxyUsername(); + password = config.proxyPassword(); } BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); AuthScope siteScope = new AuthScope(proxyHost.getHostName(), proxyHost.getPort()); From f952109721275b331a53f08d2dd8f9db61298b8e Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Fri, 18 Jul 2025 09:15:01 -0700 Subject: [PATCH 27/30] polishing --- .../io/split/client/SplitClientConfig.java | 7 +++ .../io/split/client/SplitFactoryImpl.java | 48 +++++++++---------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index eb612951..be7fd725 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -9,6 +9,7 @@ import io.split.storages.enums.OperationMode; import io.split.storages.enums.StorageMode; import org.apache.hc.core5.http.HttpHost; +import org.slf4j.LoggerFactory; import pluggable.CustomStorageWrapper; import java.io.IOException; @@ -28,6 +29,7 @@ */ public class SplitClientConfig { + private static final org.slf4j.Logger _log = LoggerFactory.getLogger(SplitClientConfig.class); public static final String LOCALHOST_DEFAULT_FILE = "split.yaml"; public static final String SDK_ENDPOINT = "https://sdk.split.io"; public static final String EVENTS_ENDPOINT = "https://events.split.io"; @@ -1140,6 +1142,11 @@ private void verifyProxy() { if (_proxyConfiguration == null) return; + if (!_proxyHost.equals("localhost")) { + _log.warn("Both the deprecated proxy configuration methods (`proxyHost`, `proxyPort`, `proxyUsername`, or `proxyPassword`) " + + "and the new `ProxyConfiguration` builder are being used. `ProxyConfiguration` will take precedence."); + } + if (!(_proxyConfiguration.getHost().getSchemeName().equals(HttpScheme.HTTP) || _proxyConfiguration.getHost().getSchemeName().equals(HttpScheme.HTTPS))) { throw new IllegalArgumentException("Proxy scheme must be either http or https."); diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index e3badac7..d40e84b3 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -629,32 +629,35 @@ private static SSLContext buildSSLContext(SplitClientConfig config) throws IOExc private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, SplitClientConfig config) { _log.info("Initializing Split SDK with proxy settings"); HttpHost proxyHost; - if (config.proxyConfiguration() != null && config.proxyConfiguration().getHost() != null) { + String userName = null; + String password = null; + if (config.proxyConfiguration() != null) { proxyHost = config.proxyConfiguration().getHost(); - } else { - _log.warn("`proxyHost`, `proxyPort` configuration methods are deprecated. Please use `ProxyConfiguration` builder instead."); - proxyHost = config.proxy(); - } - DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxyHost); - httpClientbuilder.setRoutePlanner(routePlanner); - - if ((config.proxyUsername() != null && config.proxyPassword() != null) || - (config.proxyConfiguration() != null && config.proxyConfiguration().getProxyCredentialsProvider() != null && - config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BasicCredentialsProvider)) { - _log.debug("Proxy setup using credentials"); - String userName; - String password; - if (config.proxyUsername() == null && config.proxyPassword() == null) { + if (config.proxyConfiguration().getProxyCredentialsProvider() != null && + config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BasicCredentialsProvider) { io.split.client.dtos.BasicCredentialsProvider basicAuth = (io.split.client.dtos.BasicCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider(); userName = basicAuth.getUsername(); password = basicAuth.getPassword(); - } else { - _log.warn("`proxyUsername` and `proxyPassword` configuration methods are deprecated. " + - "Please use `ProxyConfiguration` builder instead."); + } + if (config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BearerCredentialsProvider) { + _log.debug("Proxy setup using Bearer token"); + httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials( + (BearerCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider())); + } + } else { + proxyHost = config.proxy(); + if (config.proxyUsername() != null && config.proxyPassword() != null) { userName = config.proxyUsername(); password = config.proxyPassword(); } + } + + DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxyHost); + httpClientbuilder.setRoutePlanner(routePlanner); + + if (userName != null && password != null) { + _log.debug("Proxy setup using credentials"); BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); AuthScope siteScope = new AuthScope(proxyHost.getHostName(), proxyHost.getPort()); Credentials siteCreds = new UsernamePasswordCredentials(userName, @@ -662,14 +665,7 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, credsProvider.setCredentials(siteScope, siteCreds); httpClientbuilder.setDefaultCredentialsProvider(credsProvider); } - - if (config.proxyConfiguration() != null && - config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BearerCredentialsProvider) { - _log.debug("Proxy setup using Bearer token"); - httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials( - (BearerCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider())); - } - + return httpClientbuilder; } From 392d663ade409e10ead302e67063972e6a2c54c5 Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Fri, 18 Jul 2025 09:32:24 -0700 Subject: [PATCH 28/30] polishing --- .../io/split/client/SplitFactoryImpl.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index d40e84b3..d6141338 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -633,17 +633,17 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, String password = null; if (config.proxyConfiguration() != null) { proxyHost = config.proxyConfiguration().getHost(); - if (config.proxyConfiguration().getProxyCredentialsProvider() != null && - config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BasicCredentialsProvider) { - io.split.client.dtos.BasicCredentialsProvider basicAuth = - (io.split.client.dtos.BasicCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider(); - userName = basicAuth.getUsername(); - password = basicAuth.getPassword(); - } - if (config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BearerCredentialsProvider) { - _log.debug("Proxy setup using Bearer token"); - httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials( - (BearerCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider())); + if (config.proxyConfiguration().getProxyCredentialsProvider() != null) { + if (config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BasicCredentialsProvider) { + io.split.client.dtos.BasicCredentialsProvider basicAuth = + (io.split.client.dtos.BasicCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider(); + userName = basicAuth.getUsername(); + password = basicAuth.getPassword(); + } else if (config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BearerCredentialsProvider) { + _log.debug("Proxy setup using Bearer token"); + httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials( + (BearerCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider())); + } } } else { proxyHost = config.proxy(); @@ -657,7 +657,7 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, httpClientbuilder.setRoutePlanner(routePlanner); if (userName != null && password != null) { - _log.debug("Proxy setup using credentials"); + _log.debug("Proxy setup using Basic authentication"); BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); AuthScope siteScope = new AuthScope(proxyHost.getHostName(), proxyHost.getPort()); Credentials siteCreds = new UsernamePasswordCredentials(userName, From e228e1d2f4576b3e666b48db7f1c1423c5afa5fd Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Fri, 18 Jul 2025 11:40:40 -0700 Subject: [PATCH 29/30] polish --- .../io/split/client/SplitFactoryImpl.java | 55 ++++++++++++------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index d6141338..2e76e3da 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -628,34 +628,48 @@ private static SSLContext buildSSLContext(SplitClientConfig config) throws IOExc private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, SplitClientConfig config) { _log.info("Initializing Split SDK with proxy settings"); + if (config.proxyConfiguration() != null) { + return useProxyConfiguration(httpClientbuilder, config); + } else { + return useLegacyProxyConfiguration(httpClientbuilder, config); + } + } + + private static HttpClientBuilder useLegacyProxyConfiguration(HttpClientBuilder httpClientbuilder, SplitClientConfig config) { HttpHost proxyHost; String userName = null; String password = null; - if (config.proxyConfiguration() != null) { - proxyHost = config.proxyConfiguration().getHost(); - if (config.proxyConfiguration().getProxyCredentialsProvider() != null) { - if (config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BasicCredentialsProvider) { - io.split.client.dtos.BasicCredentialsProvider basicAuth = - (io.split.client.dtos.BasicCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider(); - userName = basicAuth.getUsername(); - password = basicAuth.getPassword(); - } else if (config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BearerCredentialsProvider) { - _log.debug("Proxy setup using Bearer token"); - httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials( - (BearerCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider())); - } - } - } else { - proxyHost = config.proxy(); - if (config.proxyUsername() != null && config.proxyPassword() != null) { - userName = config.proxyUsername(); - password = config.proxyPassword(); + proxyHost = config.proxy(); + if (config.proxyUsername() != null && config.proxyPassword() != null) { + userName = config.proxyUsername(); + password = config.proxyPassword(); + } + return addProxyParams(httpClientbuilder, proxyHost, userName, password); + } + + private static HttpClientBuilder useProxyConfiguration(HttpClientBuilder httpClientbuilder, SplitClientConfig config) { + HttpHost proxyHost; + String userName = null; + String password = null; + proxyHost = config.proxyConfiguration().getHost(); + if (config.proxyConfiguration().getProxyCredentialsProvider() != null) { + if (config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BasicCredentialsProvider) { + io.split.client.dtos.BasicCredentialsProvider basicAuth = + (io.split.client.dtos.BasicCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider(); + userName = basicAuth.getUsername(); + password = basicAuth.getPassword(); + } else if (config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BearerCredentialsProvider) { + _log.debug("Proxy setup using Bearer token"); + httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials( + (BearerCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider())); } } + return addProxyParams(httpClientbuilder, proxyHost, userName, password); + } + private static HttpClientBuilder addProxyParams(HttpClientBuilder httpClientbuilder, HttpHost proxyHost, String userName, String password) { DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxyHost); httpClientbuilder.setRoutePlanner(routePlanner); - if (userName != null && password != null) { _log.debug("Proxy setup using Basic authentication"); BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); @@ -665,7 +679,6 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, credsProvider.setCredentials(siteScope, siteCreds); httpClientbuilder.setDefaultCredentialsProvider(credsProvider); } - return httpClientbuilder; } From 77c681a9f8b2c755e5ec2e5490b4a941c2e1a3fb Mon Sep 17 00:00:00 2001 From: Bilal Al-Shahwany Date: Fri, 18 Jul 2025 13:20:33 -0700 Subject: [PATCH 30/30] polishing --- .../io/split/client/SplitClientConfig.java | 2 +- .../io/split/client/SplitFactoryImpl.java | 65 +++++++++---------- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index be7fd725..f32b9b09 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -1142,7 +1142,7 @@ private void verifyProxy() { if (_proxyConfiguration == null) return; - if (!_proxyHost.equals("localhost")) { + if (_proxyPort != -1) { _log.warn("Both the deprecated proxy configuration methods (`proxyHost`, `proxyPort`, `proxyUsername`, or `proxyPassword`) " + "and the new `ProxyConfiguration` builder are being used. `ProxyConfiguration` will take precedence."); } diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 2e76e3da..586e7fde 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -636,49 +636,48 @@ private static HttpClientBuilder setupProxy(HttpClientBuilder httpClientbuilder, } private static HttpClientBuilder useLegacyProxyConfiguration(HttpClientBuilder httpClientbuilder, SplitClientConfig config) { - HttpHost proxyHost; - String userName = null; - String password = null; - proxyHost = config.proxy(); + HttpHost proxyHost = config.proxy(); + httpClientbuilder = addProxyHost(httpClientbuilder, proxyHost); if (config.proxyUsername() != null && config.proxyPassword() != null) { - userName = config.proxyUsername(); - password = config.proxyPassword(); + return addProxyBasicAuth(httpClientbuilder, proxyHost, config.proxyUsername(), config.proxyPassword()); } - return addProxyParams(httpClientbuilder, proxyHost, userName, password); + + return httpClientbuilder; } private static HttpClientBuilder useProxyConfiguration(HttpClientBuilder httpClientbuilder, SplitClientConfig config) { - HttpHost proxyHost; - String userName = null; - String password = null; - proxyHost = config.proxyConfiguration().getHost(); - if (config.proxyConfiguration().getProxyCredentialsProvider() != null) { - if (config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BasicCredentialsProvider) { - io.split.client.dtos.BasicCredentialsProvider basicAuth = - (io.split.client.dtos.BasicCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider(); - userName = basicAuth.getUsername(); - password = basicAuth.getPassword(); - } else if (config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BearerCredentialsProvider) { - _log.debug("Proxy setup using Bearer token"); - httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials( - (BearerCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider())); - } + HttpHost proxyHost = config.proxyConfiguration().getHost(); + httpClientbuilder = addProxyHost(httpClientbuilder, proxyHost); + if (config.proxyConfiguration().getProxyCredentialsProvider() == null) { + return httpClientbuilder; } - return addProxyParams(httpClientbuilder, proxyHost, userName, password); + + if (config.proxyConfiguration().getProxyCredentialsProvider() instanceof io.split.client.dtos.BasicCredentialsProvider) { + io.split.client.dtos.BasicCredentialsProvider basicAuth = + (io.split.client.dtos.BasicCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider(); + return addProxyBasicAuth(httpClientbuilder, proxyHost, basicAuth.getUsername(), basicAuth.getPassword()); + } + + _log.debug("Proxy setup using Bearer token"); + httpClientbuilder.setDefaultCredentialsProvider(new HttpClientDynamicCredentials( + (BearerCredentialsProvider) config.proxyConfiguration().getProxyCredentialsProvider())); + return httpClientbuilder; } - private static HttpClientBuilder addProxyParams(HttpClientBuilder httpClientbuilder, HttpHost proxyHost, String userName, String password) { + private static HttpClientBuilder addProxyHost(HttpClientBuilder httpClientbuilder, HttpHost proxyHost) { DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxyHost); httpClientbuilder.setRoutePlanner(routePlanner); - if (userName != null && password != null) { - _log.debug("Proxy setup using Basic authentication"); - BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); - AuthScope siteScope = new AuthScope(proxyHost.getHostName(), proxyHost.getPort()); - Credentials siteCreds = new UsernamePasswordCredentials(userName, - password.toCharArray()); - credsProvider.setCredentials(siteScope, siteCreds); - httpClientbuilder.setDefaultCredentialsProvider(credsProvider); - } + return httpClientbuilder; + } + + private static HttpClientBuilder addProxyBasicAuth(HttpClientBuilder httpClientbuilder, HttpHost proxyHost, String userName, String password) { + _log.debug("Proxy setup using Basic authentication"); + BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); + AuthScope siteScope = new AuthScope(proxyHost.getHostName(), proxyHost.getPort()); + Credentials siteCreds = new UsernamePasswordCredentials(userName, + password.toCharArray()); + credsProvider.setCredentials(siteScope, siteCreds); + httpClientbuilder.setDefaultCredentialsProvider(credsProvider); return httpClientbuilder; }