Skip to content

Commit

Permalink
feat: Append custom string to User-Agent
Browse files Browse the repository at this point in the history
  • Loading branch information
SMadani committed Sep 24, 2024
1 parent 67250e7 commit 5f8815a
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

# [8.11.0] - 2024-09-24
- Added custom user agent property setting to `HttpConfig`
- Added RCS channel to Messages API
- Added `ackInboundMessage` and `revokeOutboundMessage` methods to `MessagesClient`
- Fixed `viber_service` deserialization in `com.vonage.client.messages.Channel`
Expand Down
60 changes: 51 additions & 9 deletions src/main/java/com/vonage/client/HttpConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class HttpConfig {
DEFAULT_VIDEO_BASE_URI = "https://video.api.vonage.com";

private final int timeoutMillis;
private final String apiBaseUri, restBaseUri, apiEuBaseUri, videoBaseUri;
private final String customUserAgent, apiBaseUri, restBaseUri, apiEuBaseUri, videoBaseUri;
private final Function<ApiRegion, String> regionalUriGetter;

private HttpConfig(Builder builder) {
Expand All @@ -39,6 +39,7 @@ private HttpConfig(Builder builder) {
videoBaseUri = builder.videoBaseUri;
apiEuBaseUri = builder.apiEuBaseUri;
regionalUriGetter = builder.regionalUriGetter;
customUserAgent = builder.customUserAgent;
}

/**
Expand Down Expand Up @@ -78,6 +79,16 @@ public URI getRegionalBaseUri(ApiRegion region) {
return URI.create(regionalUriGetter.apply(region));
}

/**
* Returns the custom user agent string that will be appended to the default one, if set.
*
* @return The custom user agent string to append, or {@code null} if not set.
* @since 8.11.0
*/
public String getCustomUserAgent() {
return customUserAgent;
}

@Deprecated
public boolean isDefaultApiBaseUri() {
return DEFAULT_API_BASE_URI.equals(apiBaseUri);
Expand Down Expand Up @@ -131,6 +142,11 @@ public static HttpConfig defaultConfig() {
return builder().build();
}

/**
* Entrypoint for creating a custom HttpConfig.
*
* @return A new Builder.
*/
public static Builder builder() {
return new Builder();
}
Expand All @@ -141,12 +157,27 @@ public static Builder builder() {
public static class Builder {
private int timeoutMillis = 60_000;
private Function<ApiRegion, String> regionalUriGetter = region -> "https://"+region+".vonage.com";
private String
private String customUserAgent,
apiBaseUri = DEFAULT_API_BASE_URI,
restBaseUri = DEFAULT_REST_BASE_URI,
apiEuBaseUri = DEFAULT_API_EU_BASE_URI,
videoBaseUri = DEFAULT_VIDEO_BASE_URI;

/**
* Constructor.
*
* @deprecated Will be made private in the next major version.
*/
@Deprecated
public Builder() {}

private String sanitizeUri(String uri) {
if (uri != null && uri.endsWith("/")) {
return uri.substring(0, uri.length() - 1);
}
return uri;
}

/**
* Sets the socket timeout for requests. By default, this is one minute (60000 ms).
* <br>
Expand Down Expand Up @@ -249,6 +280,24 @@ public Builder regionalUriGetter(Function<ApiRegion, String> uriGetter) {
return this;
}

/**
* Appends a custom string to the default {@code User-Agent} header. This is mainly used for
* derivatives of the SDK, or to distinguish particular users / use cases.
*
* @param userAgent The user agent string to append to the existing one. Must be less than 128 characters.
* @return This builder.
* @since 8.11.0
*/
public Builder appendUserAgent(String userAgent) {
if ((this.customUserAgent = Objects.requireNonNull(userAgent).trim()).length() > 127) {
throw new IllegalArgumentException("User agent string must be less than 128 characters in length.");
}
if (customUserAgent.isEmpty()) {
throw new IllegalArgumentException("Custom user agent string cannot be blank.");
}
return this;
}

/**
* Builds the HttpConfig.
*
Expand All @@ -257,12 +306,5 @@ public Builder regionalUriGetter(Function<ApiRegion, String> uriGetter) {
public HttpConfig build() {
return new HttpConfig(this);
}

private String sanitizeUri(String uri) {
if (uri != null && uri.endsWith("/")) {
return uri.substring(0, uri.length() - 1);
}
return uri;
}
}
}
39 changes: 37 additions & 2 deletions src/main/java/com/vonage/client/HttpWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ public HttpWrapper(HttpConfig httpConfig, AuthMethod... authMethods) {
this(httpConfig, new AuthCollection(authMethods));
}

/**
* Gets the underlying {@link HttpClient} instance used by the SDK.
*
* @return The Apache HTTP client instance.
*/
public HttpClient getHttpClient() {
if (httpClient == null) {
httpClient = createHttpClient();
Expand Down Expand Up @@ -106,6 +111,11 @@ public void setHttpConfig(HttpConfig httpConfig) {
this.httpConfig = httpConfig;
}

/**
* Gets the authentication settings used by the client.
*
* @return The available authentication methods object.
*/
public AuthCollection getAuthCollection() {
return authCollection;
}
Expand Down Expand Up @@ -137,18 +147,43 @@ protected HttpClient createHttpClient() {

return HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.setUserAgent(USER_AGENT)
.setUserAgent(getUserAgent())
.setDefaultRequestConfig(requestConfig)
.useSystemProperties()
.disableRedirectHandling()
.build();
}

/**
* Gets the HTTP configuration settings for the client.
*
* @return The request configuration settings object.
*/
public HttpConfig getHttpConfig() {
return httpConfig;
}

/**
* Gets the {@code User-Agent} header to be used in HTTP requests.
* This includes the Java runtime and SDK version, as well as the custom user agent string, if present.
*
* @return The user agent string.
*/
public String getUserAgent() {
return USER_AGENT;
String ua = USER_AGENT, custom = httpConfig.getCustomUserAgent();
if (custom != null) {
ua += " " + httpConfig.getCustomUserAgent();
}
return ua;
}

/**
* Gets the SDK version.
*
* @return The SDK version as a string.
* @since 8.11.0
*/
public String getClientVersion() {
return CLIENT_VERSION;
}
}
14 changes: 14 additions & 0 deletions src/test/java/com/vonage/client/HttpConfigTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,18 @@ public void testApiRegionEnum() {
assertEquals(region, ApiRegion.fromString(toString));
}
}

@Test
public void testCustomUserAgentValidation() {
assertEquals("Abc123", HttpConfig.builder().appendUserAgent(" Abc123\t\n").build().getCustomUserAgent());
assertThrows(NullPointerException.class, () ->
HttpConfig.builder().appendUserAgent(null).build()
);
assertThrows(IllegalArgumentException.class, () ->
HttpConfig.builder().appendUserAgent(" \t\n").build()
);
assertThrows(IllegalArgumentException.class, () ->
HttpConfig.builder().appendUserAgent("d".repeat(128)).build()
);
}
}
17 changes: 17 additions & 0 deletions src/test/java/com/vonage/client/HttpWrapperTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,21 @@ public void testDefaultConstructorSetsDefaultConfigValues() {
assertNotNull(config);
HttpConfigTest.assertDefaults(config);
}

@Test
public void testDefaultUserAgent() {
assertNull(wrapper.getHttpConfig().getCustomUserAgent());
assertEquals(
"vonage-java-sdk/"+wrapper.getClientVersion()+" java/" + System.getProperty("java.version"),
wrapper.getUserAgent()
);
}

@Test
public void testValidCustomUserAgent() {
String customUa = "my-custom-agent", defaultUa = wrapper.getUserAgent();
wrapper = new HttpWrapper(HttpConfig.builder().appendUserAgent(customUa).build());
assertEquals(customUa, wrapper.getHttpConfig().getCustomUserAgent());
assertEquals(defaultUa + " " + customUa, wrapper.getUserAgent());
}
}

0 comments on commit 5f8815a

Please sign in to comment.