Skip to content

Commit 5cc0084

Browse files
authored
Merge pull request #527 from maxmind/horgh/http-client
Add support for custom HttpClient in WebServiceClient.Builder
2 parents 77d3f85 + b457b90 commit 5cc0084

File tree

3 files changed

+84
-7
lines changed

3 files changed

+84
-7
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ CHANGELOG
55
------------------
66

77
* Added `SECUREPAY` to the `Payment.Processor` enum.
8+
* `WebServiceClient.Builder` now has an `httpClient()` method to allow
9+
passing in a custom `HttpClient`.
810

911
3.8.0 (2025-06-09)
1012
------------------

src/main/java/com/maxmind/minfraud/WebServiceClient.java

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,16 @@ private WebServiceClient(WebServiceClient.Builder builder) {
6464
.getBytes(StandardCharsets.UTF_8));
6565

6666
requestTimeout = builder.requestTimeout;
67-
HttpClient.Builder httpClientBuilder = HttpClient.newBuilder()
68-
.proxy(builder.proxy);
69-
if (builder.connectTimeout != null) {
70-
httpClientBuilder.connectTimeout(builder.connectTimeout);
67+
if (builder.httpClient != null) {
68+
httpClient = builder.httpClient;
69+
} else {
70+
HttpClient.Builder httpClientBuilder = HttpClient.newBuilder()
71+
.proxy(builder.proxy);
72+
if (builder.connectTimeout != null) {
73+
httpClientBuilder.connectTimeout(builder.connectTimeout);
74+
}
75+
httpClient = httpClientBuilder.build();
7176
}
72-
httpClient = httpClientBuilder.build();
73-
7477
}
7578

7679
/**
@@ -102,7 +105,8 @@ public static final class Builder {
102105
Duration requestTimeout;
103106

104107
List<String> locales = Collections.singletonList("en");
105-
private ProxySelector proxy = ProxySelector.getDefault();
108+
private ProxySelector proxy;
109+
private HttpClient httpClient;
106110

107111
/**
108112
* @param accountId Your MaxMind account ID.
@@ -188,12 +192,38 @@ public Builder proxy(ProxySelector val) {
188192
return this;
189193
}
190194

195+
/**
196+
* @param val the HttpClient to use when making requests. When provided,
197+
* connectTimeout and proxy settings will be ignored as the
198+
* custom client should handle these configurations.
199+
* @return Builder object
200+
*/
201+
public Builder httpClient(HttpClient val) {
202+
httpClient = val;
203+
return this;
204+
}
191205

192206
/**
193207
* @return an instance of {@code WebServiceClient} created from the fields set on this
194208
* builder.
195209
*/
196210
public WebServiceClient build() {
211+
if (httpClient != null) {
212+
if (connectTimeout != null) {
213+
throw new IllegalArgumentException(
214+
"Cannot set both httpClient and connectTimeout. "
215+
+ "Configure timeouts on the provided HttpClient instead.");
216+
}
217+
if (proxy != null) {
218+
throw new IllegalArgumentException(
219+
"Cannot set both httpClient and proxy. "
220+
+ "Configure proxy on the provided HttpClient instead.");
221+
}
222+
} else {
223+
if (proxy == null) {
224+
proxy = ProxySelector.getDefault();
225+
}
226+
}
197227
return new WebServiceClient(this);
198228
}
199229
}

src/test/java/com/maxmind/minfraud/WebServiceClientTest.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838
import com.maxmind.minfraud.response.IpRiskReason;
3939
import com.maxmind.minfraud.response.ScoreResponse;
4040
import java.net.InetAddress;
41+
import java.net.ProxySelector;
42+
import java.net.http.HttpClient;
43+
import java.time.Duration;
4144
import java.util.List;
4245
import org.junit.jupiter.api.Test;
4346
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -357,4 +360,46 @@ private WebServiceClient createClient(String service, int status, String content
357360
.disableHttps()
358361
.build();
359362
}
363+
364+
@Test
365+
public void testHttpClientWorks() {
366+
HttpClient customClient = HttpClient.newBuilder().build();
367+
368+
WebServiceClient client = new WebServiceClient.Builder(6, "0123456789")
369+
.httpClient(customClient)
370+
.build();
371+
372+
// Verify the client was created successfully
373+
assertEquals("WebServiceClient{host='minfraud.maxmind.com', port=443, useHttps=true, locales=[en], httpClient=" + customClient + "}", client.toString());
374+
}
375+
376+
@Test
377+
public void testHttpClientWithConnectTimeoutThrowsException() {
378+
HttpClient customClient = HttpClient.newBuilder().build();
379+
380+
Exception ex = assertThrows(IllegalArgumentException.class, () ->
381+
new WebServiceClient.Builder(6, "0123456789")
382+
.httpClient(customClient)
383+
.connectTimeout(Duration.ofSeconds(5))
384+
.build()
385+
);
386+
387+
assertEquals("Cannot set both httpClient and connectTimeout. " +
388+
"Configure timeouts on the provided HttpClient instead.", ex.getMessage());
389+
}
390+
391+
@Test
392+
public void testHttpClientWithProxyThrowsException() {
393+
HttpClient customClient = HttpClient.newBuilder().build();
394+
395+
Exception ex = assertThrows(IllegalArgumentException.class, () ->
396+
new WebServiceClient.Builder(6, "0123456789")
397+
.httpClient(customClient)
398+
.proxy(java.net.ProxySelector.of(null))
399+
.build()
400+
);
401+
402+
assertEquals("Cannot set both httpClient and proxy. " +
403+
"Configure proxy on the provided HttpClient instead.", ex.getMessage());
404+
}
360405
}

0 commit comments

Comments
 (0)