Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for proxies in HttpConfig #556

Merged
merged 3 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
}
Loading