Skip to content

Commit

Permalink
feat: Add support for proxies in HttpConfig (#556)
Browse files Browse the repository at this point in the history
  • Loading branch information
SMadani authored Dec 3, 2024
1 parent 17f5f10 commit 8a93a6c
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 11 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>com.vonage</groupId>
<artifactId>server-sdk</artifactId>
<version>8.14.0</version>
<version>8.15.0</version>

<name>Vonage Java Server SDK</name>
<description>Java client for Vonage APIs</description>
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/vonage/client/AbstractMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down
37 changes: 37 additions & 0 deletions src/main/java/com/vonage/client/HttpConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ public class HttpConfig {
private final int timeoutMillis;
private final String customUserAgent, apiBaseUri, restBaseUri, apiEuBaseUri, videoBaseUri;
private final Function<ApiRegion, String> 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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -156,6 +168,7 @@ public static Builder builder() {
*/
public static class Builder {
private int timeoutMillis = 60_000;
private URI proxy;
private Function<ApiRegion, String> regionalUriGetter = region -> "https://"+region+".vonage.com";
private String customUserAgent,
apiBaseUri = DEFAULT_API_BASE_URI,
Expand Down Expand Up @@ -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.
*
Expand Down
22 changes: 13 additions & 9 deletions src/main/java/com/vonage/client/HttpWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
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;
import org.apache.http.config.SocketConfig;
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;

Expand All @@ -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);

Expand Down Expand Up @@ -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();
}

/**
Expand Down
24 changes: 24 additions & 0 deletions src/test/java/com/vonage/client/HttpWrapperTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;
Expand Down Expand Up @@ -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);
}
}

0 comments on commit 8a93a6c

Please sign in to comment.