diff --git a/CHANGELOG.md b/CHANGELOG.md
index 78dbe731e..3958c5eca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
+# [8.15.0] - 2024-12-03
+- Added proxy support to `HttpConfig.Builder`
+- Basic auth in header instead of query params in SMS API
+
# [8.14.0] - 2024-11-14
- Close HTTP responses to prevent resource leaks
- Added `RedactResponseException` and deprecated `VonageBadRequestException`
diff --git a/pom.xml b/pom.xml
index 903f04152..838a54c3d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.vonage
server-sdk
- 8.14.0
+ 8.15.0
Vonage Java Server SDK
Java client for Vonage APIs
diff --git a/src/main/java/com/vonage/client/AbstractMethod.java b/src/main/java/com/vonage/client/AbstractMethod.java
index e2e5367ca..76c5f1825 100644
--- a/src/main/java/com/vonage/client/AbstractMethod.java
+++ b/src/main/java/com/vonage/client/AbstractMethod.java
@@ -17,6 +17,7 @@
import com.vonage.client.auth.*;
import org.apache.commons.logging.LogFactory;
+import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
@@ -71,7 +72,7 @@ protected ResultT postProcessParsedResponse(ResultT response) {
@Override
public ResultT execute(RequestT request) throws VonageResponseParseException, VonageClientException {
HttpUriRequest httpRequest = applyAuth(makeRequest(request))
- .setHeader("User-Agent", httpWrapper.getUserAgent())
+ .setHeader(HttpHeaders.USER_AGENT, httpWrapper.getUserAgent())
.setCharset(StandardCharsets.UTF_8).build();
try (CloseableHttpResponse response = httpWrapper.getHttpClient().execute(httpRequest)) {
diff --git a/src/main/java/com/vonage/client/HttpConfig.java b/src/main/java/com/vonage/client/HttpConfig.java
index df96168a2..735bc2659 100644
--- a/src/main/java/com/vonage/client/HttpConfig.java
+++ b/src/main/java/com/vonage/client/HttpConfig.java
@@ -29,11 +29,13 @@ public class HttpConfig {
private final int timeoutMillis;
private final String customUserAgent, apiBaseUri, restBaseUri, apiEuBaseUri, videoBaseUri;
private final Function regionalUriGetter;
+ private final URI proxy;
private HttpConfig(Builder builder) {
if ((timeoutMillis = builder.timeoutMillis) < 10) {
throw new IllegalArgumentException("Timeout must be greater than 10ms.");
}
+ proxy = builder.proxy;
apiBaseUri = builder.apiBaseUri;
restBaseUri = builder.restBaseUri;
videoBaseUri = builder.videoBaseUri;
@@ -89,6 +91,16 @@ public String getCustomUserAgent() {
return customUserAgent;
}
+ /**
+ * Returns the proxy URL to use for the underlying HTTP client configuration.
+ *
+ * @return The proxy URI, or {@code null} if not set.
+ * @since 8.15.0
+ */
+ public URI getProxy() {
+ return proxy;
+ }
+
@Deprecated
public boolean isDefaultApiBaseUri() {
return DEFAULT_API_BASE_URI.equals(apiBaseUri);
@@ -156,6 +168,7 @@ public static Builder builder() {
*/
public static class Builder {
private int timeoutMillis = 60_000;
+ private URI proxy;
private Function regionalUriGetter = region -> "https://"+region+".vonage.com";
private String customUserAgent,
apiBaseUri = DEFAULT_API_BASE_URI,
@@ -196,6 +209,30 @@ public Builder timeoutMillis(int timeoutMillis) {
return this;
}
+ /**
+ * Sets the proxy to use for requests. This will route requests through the specified URL.
+ *
+ * @param proxy The proxy URI to use as a string.
+ * @return This builder.
+ * @since 8.15.0
+ * @throws IllegalArgumentException If the proxy URI is invalid.
+ */
+ public Builder proxy(String proxy) {
+ return proxy(URI.create(proxy));
+ }
+
+ /**
+ * Sets the proxy to use for requests. This will route requests through the specified URL.
+ *
+ * @param proxy The proxy URI to use.
+ * @return This builder.
+ * @since 8.15.0
+ */
+ public Builder proxy(URI proxy) {
+ this.proxy = proxy;
+ return this;
+ }
+
/**
* Replaces the URI used in "api" endpoints.
*
diff --git a/src/main/java/com/vonage/client/HttpWrapper.java b/src/main/java/com/vonage/client/HttpWrapper.java
index c9c5384e7..a1e7faadf 100644
--- a/src/main/java/com/vonage/client/HttpWrapper.java
+++ b/src/main/java/com/vonage/client/HttpWrapper.java
@@ -19,6 +19,7 @@
import com.vonage.client.auth.AuthCollection;
import com.vonage.client.auth.AuthMethod;
import com.vonage.client.auth.JWTAuthMethod;
+import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.ConnectionConfig;
@@ -26,6 +27,7 @@
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
@@ -35,7 +37,7 @@
public class HttpWrapper {
private static final String
CLIENT_NAME = "vonage-java-sdk",
- CLIENT_VERSION = "8.14.0",
+ CLIENT_VERSION = "8.15.0",
JAVA_VERSION = System.getProperty("java.version"),
USER_AGENT = String.format("%s/%s java/%s", CLIENT_NAME, CLIENT_VERSION, JAVA_VERSION);
@@ -131,28 +133,30 @@ protected CloseableHttpClient createHttpClient() {
connectionManager.setDefaultMaxPerRoute(200);
connectionManager.setMaxTotal(200);
connectionManager.setDefaultConnectionConfig(
- ConnectionConfig.custom()
- .setCharset(StandardCharsets.UTF_8)
- .build()
+ ConnectionConfig.custom().setCharset(StandardCharsets.UTF_8).build()
);
connectionManager.setDefaultSocketConfig(SocketConfig.custom().setTcpNoDelay(true).build());
// Need to work out a good value for the following:
// threadSafeClientConnManager.setValidateAfterInactivity();
-
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(httpConfig.getTimeoutMillis())
.setConnectionRequestTimeout(httpConfig.getTimeoutMillis())
.setSocketTimeout(httpConfig.getTimeoutMillis())
.build();
- return HttpClientBuilder.create()
+ HttpClientBuilder clientBuilder = HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.setUserAgent(getUserAgent())
.setDefaultRequestConfig(requestConfig)
- .useSystemProperties()
- .disableRedirectHandling()
- .build();
+ .useSystemProperties().disableRedirectHandling();
+
+ URI proxy = httpConfig.getProxy();
+ if (proxy != null) {
+ clientBuilder.setProxy(new HttpHost(proxy.getHost(), proxy.getPort(), proxy.getScheme()));
+ }
+
+ return clientBuilder.build();
}
/**
diff --git a/src/test/java/com/vonage/client/HttpWrapperTest.java b/src/test/java/com/vonage/client/HttpWrapperTest.java
index f496eaab6..3aac855a7 100644
--- a/src/test/java/com/vonage/client/HttpWrapperTest.java
+++ b/src/test/java/com/vonage/client/HttpWrapperTest.java
@@ -15,6 +15,10 @@
*/
package com.vonage.client;
+import static com.vonage.client.TestUtils.API_KEY;
+import static com.vonage.client.TestUtils.API_SECRET;
+import com.vonage.client.application.ApplicationClient;
+import com.vonage.client.auth.ApiKeyHeaderAuthMethod;
import com.vonage.client.auth.AuthCollection;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
@@ -67,4 +71,24 @@ public void testValidCustomUserAgent() {
assertEquals(customUa, wrapper.getHttpConfig().getCustomUserAgent());
assertEquals(defaultUa + " " + customUa, wrapper.getUserAgent());
}
+
+ @Test
+ public void testProxy() {
+ var headerAuth = new ApiKeyHeaderAuthMethod(API_KEY, API_SECRET);
+ wrapper = new HttpWrapper(headerAuth);
+ assertNull(wrapper.getHttpConfig().getProxy());
+
+ var appClient = new ApplicationClient(wrapper);
+ assertThrows(VonageApiResponseException.class, appClient::listApplications);
+
+ wrapper = new HttpWrapper(HttpConfig.builder().proxy("http://localhost:8080").build(), headerAuth);
+ var proxyUri = wrapper.getHttpConfig().getProxy();
+ assertNotNull(proxyUri);
+ assertEquals("localhost", proxyUri.getHost());
+ assertEquals(8080, proxyUri.getPort());
+ assertEquals("http", proxyUri.getScheme());
+
+ appClient = new ApplicationClient(wrapper);
+ assertThrows(VonageMethodFailedException.class, appClient::listApplications);
+ }
}