Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit 3d36228

Browse files
prepare 5.2.0 release (#217)
1 parent 06ebc5d commit 3d36228

File tree

10 files changed

+206
-1
lines changed

10 files changed

+206
-1
lines changed

src/main/java/com/launchdarkly/sdk/server/ComponentsImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ public HttpConfiguration createHttpConfiguration(BasicConfiguration basicConfigu
262262
proxy,
263263
proxyAuth,
264264
socketTimeout,
265+
socketFactory,
265266
sslSocketFactory,
266267
trustManager,
267268
headers.build()

src/main/java/com/launchdarkly/sdk/server/HttpConfigurationImpl.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.time.Duration;
99
import java.util.Map;
1010

11+
import javax.net.SocketFactory;
1112
import javax.net.ssl.SSLSocketFactory;
1213
import javax.net.ssl.X509TrustManager;
1314

@@ -16,17 +17,20 @@ final class HttpConfigurationImpl implements HttpConfiguration {
1617
final Proxy proxy;
1718
final HttpAuthentication proxyAuth;
1819
final Duration socketTimeout;
20+
final SocketFactory socketFactory;
1921
final SSLSocketFactory sslSocketFactory;
2022
final X509TrustManager trustManager;
2123
final ImmutableMap<String, String> defaultHeaders;
2224

2325
HttpConfigurationImpl(Duration connectTimeout, Proxy proxy, HttpAuthentication proxyAuth,
24-
Duration socketTimeout, SSLSocketFactory sslSocketFactory, X509TrustManager trustManager,
26+
Duration socketTimeout, SocketFactory socketFactory,
27+
SSLSocketFactory sslSocketFactory, X509TrustManager trustManager,
2528
ImmutableMap<String, String> defaultHeaders) {
2629
this.connectTimeout = connectTimeout;
2730
this.proxy = proxy;
2831
this.proxyAuth = proxyAuth;
2932
this.socketTimeout = socketTimeout;
33+
this.socketFactory = socketFactory;
3034
this.sslSocketFactory = sslSocketFactory;
3135
this.trustManager = trustManager;
3236
this.defaultHeaders = defaultHeaders;
@@ -51,6 +55,11 @@ public HttpAuthentication getProxyAuthentication() {
5155
public Duration getSocketTimeout() {
5256
return socketTimeout;
5357
}
58+
59+
@Override
60+
public SocketFactory getSocketFactory() {
61+
return socketFactory;
62+
}
5463

5564
@Override
5665
public SSLSocketFactory getSslSocketFactory() {

src/main/java/com/launchdarkly/sdk/server/Util.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ static void configureHttpClientBuilder(HttpConfiguration config, OkHttpClient.Bu
4343
.readTimeout(config.getSocketTimeout())
4444
.writeTimeout(config.getSocketTimeout())
4545
.retryOnConnectionFailure(false); // we will implement our own retry logic
46+
47+
if (config.getSocketFactory() != null) {
48+
builder.socketFactory(config.getSocketFactory());
49+
}
4650

4751
if (config.getSslSocketFactory() != null) {
4852
builder.sslSocketFactory(config.getSslSocketFactory(), config.getTrustManager());

src/main/java/com/launchdarkly/sdk/server/integrations/HttpConfigurationBuilder.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import java.time.Duration;
88

9+
import javax.net.SocketFactory;
910
import javax.net.ssl.SSLSocketFactory;
1011
import javax.net.ssl.X509TrustManager;
1112

@@ -45,6 +46,7 @@ public abstract class HttpConfigurationBuilder implements HttpConfigurationFacto
4546
protected String proxyHost;
4647
protected int proxyPort;
4748
protected Duration socketTimeout = DEFAULT_SOCKET_TIMEOUT;
49+
protected SocketFactory socketFactory;
4850
protected SSLSocketFactory sslSocketFactory;
4951
protected X509TrustManager trustManager;
5052
protected String wrapperName;
@@ -105,6 +107,19 @@ public HttpConfigurationBuilder socketTimeout(Duration socketTimeout) {
105107
return this;
106108
}
107109

110+
/**
111+
* Specifies a custom socket configuration for HTTP connections to LaunchDarkly.
112+
* <p>
113+
* This uses the standard Java interfaces for configuring socket connections.
114+
*
115+
* @param socketFactory the socket factory
116+
* @return the builder
117+
*/
118+
public HttpConfigurationBuilder socketFactory(SocketFactory socketFactory) {
119+
this.socketFactory = socketFactory;
120+
return this;
121+
}
122+
108123
/**
109124
* Specifies a custom security configuration for HTTPS connections to LaunchDarkly.
110125
* <p>

src/main/java/com/launchdarkly/sdk/server/interfaces/HttpConfiguration.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.time.Duration;
77
import java.util.Map;
88

9+
import javax.net.SocketFactory;
910
import javax.net.ssl.SSLSocketFactory;
1011
import javax.net.ssl.X509TrustManager;
1112

@@ -53,6 +54,15 @@ public interface HttpConfiguration {
5354
* @return the socket timeout; must not be null
5455
*/
5556
Duration getSocketTimeout();
57+
58+
/**
59+
* The configured socket factory for insecure connections.
60+
*
61+
* @return a SocketFactory or null
62+
*/
63+
default SocketFactory getSocketFactory() {
64+
return null;
65+
}
5666

5767
/**
5868
* The configured socket factory for secure connections.

src/test/java/com/launchdarkly/sdk/server/DefaultEventSenderTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.concurrent.TimeUnit;
1717

1818
import static com.launchdarkly.sdk.server.TestComponents.clientContext;
19+
import static com.launchdarkly.sdk.server.TestUtil.makeSocketFactorySingleHost;
1920
import static com.launchdarkly.sdk.server.TestHttpUtil.httpsServerWithSelfSignedCert;
2021
import static com.launchdarkly.sdk.server.TestHttpUtil.makeStartedServer;
2122
import static com.launchdarkly.sdk.server.interfaces.EventSender.EventDataKind.ANALYTICS;
@@ -32,6 +33,7 @@
3233
import static org.junit.Assert.assertNull;
3334
import static org.junit.Assert.assertTrue;
3435

36+
import okhttp3.HttpUrl;
3537
import okhttp3.mockwebserver.MockResponse;
3638
import okhttp3.mockwebserver.MockWebServer;
3739
import okhttp3.mockwebserver.RecordedRequest;
@@ -300,6 +302,26 @@ public void httpClientCanUseCustomTlsConfig() throws Exception {
300302
}
301303
}
302304

305+
@Test
306+
public void httpClientCanUseCustomSocketFactory() throws Exception {
307+
try (MockWebServer server = makeStartedServer(eventsSuccessResponse())) {
308+
HttpUrl serverUrl = server.url("/");
309+
LDConfig config = new LDConfig.Builder()
310+
.http(Components.httpConfiguration().socketFactory(makeSocketFactorySingleHost(serverUrl.host(), serverUrl.port())))
311+
.build();
312+
313+
URI uriWithWrongPort = URI.create("http://localhost:1");
314+
try (EventSender es = makeEventSender(config)) {
315+
EventSender.Result result = es.sendEventData(DIAGNOSTICS, FAKE_DATA, 1, uriWithWrongPort);
316+
317+
assertTrue(result.isSuccess());
318+
assertFalse(result.isMustShutDown());
319+
}
320+
321+
assertEquals(1, server.getRequestCount());
322+
}
323+
}
324+
303325
@Test
304326
public void baseUriDoesNotNeedTrailingSlash() throws Exception {
305327
try (MockWebServer server = makeStartedServer(eventsSuccessResponse())) {

src/test/java/com/launchdarkly/sdk/server/DefaultFeatureRequestorTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
import java.net.URI;
99
import java.util.Map;
1010

11+
import javax.net.SocketFactory;
1112
import javax.net.ssl.SSLHandshakeException;
1213

1314
import static com.launchdarkly.sdk.server.TestComponents.clientContext;
15+
import static com.launchdarkly.sdk.server.TestUtil.makeSocketFactorySingleHost;
1416
import static com.launchdarkly.sdk.server.TestHttpUtil.httpsServerWithSelfSignedCert;
1517
import static com.launchdarkly.sdk.server.TestHttpUtil.jsonResponse;
1618
import static com.launchdarkly.sdk.server.TestHttpUtil.makeStartedServer;
@@ -169,6 +171,24 @@ public void httpClientCanUseCustomTlsConfig() throws Exception {
169171
}
170172
}
171173

174+
@Test
175+
public void httpClientCanUseCustomSocketFactory() throws Exception {
176+
try (MockWebServer server = makeStartedServer(jsonResponse(allDataJson))) {
177+
HttpUrl serverUrl = server.url("/");
178+
LDConfig config = new LDConfig.Builder()
179+
.http(Components.httpConfiguration().socketFactory(makeSocketFactorySingleHost(serverUrl.host(), serverUrl.port())))
180+
.build();
181+
182+
URI uriWithWrongPort = URI.create("http://localhost:1");
183+
try (DefaultFeatureRequestor r = new DefaultFeatureRequestor(makeHttpConfig(config), uriWithWrongPort)) {
184+
FeatureRequestor.AllData data = r.getAllData(false);
185+
verifyExpectedData(data);
186+
187+
assertEquals(1, server.getRequestCount());
188+
}
189+
}
190+
}
191+
172192
@Test
173193
public void httpClientCanUseProxyConfig() throws Exception {
174194
URI fakeBaseUri = URI.create("http://not-a-real-host");

src/test/java/com/launchdarkly/sdk/server/StreamProcessorTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import static com.launchdarkly.sdk.server.TestComponents.dataStoreThatThrowsException;
4949
import static com.launchdarkly.sdk.server.TestHttpUtil.eventStreamResponse;
5050
import static com.launchdarkly.sdk.server.TestHttpUtil.makeStartedServer;
51+
import static com.launchdarkly.sdk.server.TestUtil.makeSocketFactorySingleHost;
5152
import static com.launchdarkly.sdk.server.TestUtil.requireDataSourceStatus;
5253
import static com.launchdarkly.sdk.server.TestUtil.shouldNotTimeOut;
5354
import static com.launchdarkly.sdk.server.TestUtil.shouldTimeOut;
@@ -669,6 +670,27 @@ public void httpClientCanUseCustomTlsConfig() throws Exception {
669670
}
670671
}
671672
}
673+
674+
@Test
675+
public void httpClientCanUseCustomSocketFactory() throws Exception {
676+
final ConnectionErrorSink errorSink = new ConnectionErrorSink();
677+
try (MockWebServer server = makeStartedServer(eventStreamResponse(STREAM_RESPONSE_WITH_EMPTY_DATA))) {
678+
HttpUrl serverUrl = server.url("/");
679+
LDConfig config = new LDConfig.Builder()
680+
.http(Components.httpConfiguration().socketFactory(makeSocketFactorySingleHost(serverUrl.host(), serverUrl.port())))
681+
.build();
682+
683+
URI uriWithWrongPort = URI.create("http://localhost:1");
684+
try (StreamProcessor sp = createStreamProcessorWithRealHttp(config, uriWithWrongPort)) {
685+
sp.connectionErrorHandler = errorSink;
686+
Future<Void> ready = sp.start();
687+
ready.get();
688+
689+
assertNull(errorSink.errors.peek());
690+
assertEquals(1, server.getRequestCount());
691+
}
692+
}
693+
}
672694

673695
@Test
674696
public void httpClientCanUseProxyConfig() throws Exception {

src/test/java/com/launchdarkly/sdk/server/TestUtil.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
import org.hamcrest.TypeSafeDiagnosingMatcher;
1818

1919
import java.io.IOException;
20+
import java.net.InetAddress;
21+
import java.net.InetSocketAddress;
22+
import java.net.Socket;
23+
import java.net.SocketAddress;
2024
import java.time.Duration;
2125
import java.time.Instant;
2226
import java.util.HashSet;
@@ -29,6 +33,8 @@
2933
import java.util.concurrent.TimeoutException;
3034
import java.util.function.Supplier;
3135

36+
import javax.net.SocketFactory;
37+
3238
import static com.launchdarkly.sdk.server.DataModel.FEATURES;
3339
import static com.launchdarkly.sdk.server.DataModel.SEGMENTS;
3440
import static org.hamcrest.MatcherAssert.assertThat;
@@ -255,4 +261,65 @@ protected boolean matchesSafely(LDValue item, Description mismatchDescription) {
255261
}
256262
};
257263
}
264+
265+
// returns a socket factory that creates sockets that only connect to host and port
266+
static SocketFactorySingleHost makeSocketFactorySingleHost(String host, int port) {
267+
return new SocketFactorySingleHost(host, port);
268+
}
269+
270+
private static final class SocketSingleHost extends Socket {
271+
private final String host;
272+
private final int port;
273+
274+
SocketSingleHost(String host, int port) {
275+
this.host = host;
276+
this.port = port;
277+
}
278+
279+
@Override public void connect(SocketAddress endpoint) throws IOException {
280+
super.connect(new InetSocketAddress(this.host, this.port), 0);
281+
}
282+
283+
@Override public void connect(SocketAddress endpoint, int timeout) throws IOException {
284+
super.connect(new InetSocketAddress(this.host, this.port), timeout);
285+
}
286+
}
287+
288+
public static final class SocketFactorySingleHost extends SocketFactory {
289+
private final String host;
290+
private final int port;
291+
292+
public SocketFactorySingleHost(String host, int port) {
293+
this.host = host;
294+
this.port = port;
295+
}
296+
297+
@Override public Socket createSocket() throws IOException {
298+
return new SocketSingleHost(this.host, this.port);
299+
}
300+
301+
@Override public Socket createSocket(String host, int port) throws IOException {
302+
Socket socket = createSocket();
303+
socket.connect(new InetSocketAddress(this.host, this.port));
304+
return socket;
305+
}
306+
307+
@Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
308+
Socket socket = createSocket();
309+
socket.connect(new InetSocketAddress(this.host, this.port));
310+
return socket;
311+
}
312+
313+
@Override public Socket createSocket(InetAddress host, int port) throws IOException {
314+
Socket socket = createSocket();
315+
socket.connect(new InetSocketAddress(this.host, this.port));
316+
return socket;
317+
}
318+
319+
@Override public Socket createSocket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException {
320+
Socket socket = createSocket();
321+
socket.connect(new InetSocketAddress(this.host, this.port));
322+
return socket;
323+
}
324+
}
258325
}

src/test/java/com/launchdarkly/sdk/server/integrations/HttpConfigurationBuilderTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.security.cert.X509Certificate;
1818
import java.time.Duration;
1919

20+
import javax.net.SocketFactory;
2021
import javax.net.ssl.SSLSocketFactory;
2122
import javax.net.ssl.X509TrustManager;
2223

@@ -46,6 +47,7 @@ public void testDefaults() {
4647
assertNull(hc.getProxy());
4748
assertNull(hc.getProxyAuthentication());
4849
assertEquals(DEFAULT_SOCKET_TIMEOUT, hc.getSocketTimeout());
50+
assertNull(hc.getSocketFactory());
4951
assertNull(hc.getSslSocketFactory());
5052
assertNull(hc.getTrustManager());
5153
assertEquals(buildBasicHeaders().build(), ImmutableMap.copyOf(hc.getDefaultHeaders()));
@@ -99,6 +101,15 @@ public void testSocketTimeout() {
99101
assertEquals(DEFAULT_SOCKET_TIMEOUT, hc2.getSocketTimeout());
100102
}
101103

104+
@Test
105+
public void testSocketFactory() {
106+
SocketFactory sf = new StubSocketFactory();
107+
HttpConfiguration hc = Components.httpConfiguration()
108+
.socketFactory(sf)
109+
.createHttpConfiguration(BASIC_CONFIG);
110+
assertSame(sf, hc.getSocketFactory());
111+
}
112+
102113
@Test
103114
public void testSslOptions() {
104115
SSLSocketFactory sf = new StubSSLSocketFactory();
@@ -125,6 +136,30 @@ public void testWrapperWithVersion() {
125136
.createHttpConfiguration(BASIC_CONFIG);
126137
assertEquals("Scala/0.1.0", ImmutableMap.copyOf(hc.getDefaultHeaders()).get("X-LaunchDarkly-Wrapper"));
127138
}
139+
140+
public static class StubSocketFactory extends SocketFactory {
141+
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
142+
throws IOException {
143+
return null;
144+
}
145+
146+
public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
147+
throws IOException, UnknownHostException {
148+
return null;
149+
}
150+
151+
public Socket createSocket(InetAddress host, int port) throws IOException {
152+
return null;
153+
}
154+
155+
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
156+
return null;
157+
}
158+
159+
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
160+
return null;
161+
}
162+
}
128163

129164
public static class StubSSLSocketFactory extends SSLSocketFactory {
130165
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)

0 commit comments

Comments
 (0)