From f3c3f3b30620ad62dc502cf79bf121ec1773396e Mon Sep 17 00:00:00 2001 From: Vijay Panghal Date: Thu, 15 Dec 2016 11:04:02 -0800 Subject: [PATCH] Make user agent header configurable Jclouds sends default user agent string with each request to cloud services. But some of the application would like to overide this and send custom user agent instead. This commit define a string property to overide this default user agent string. This property will be applied to all outgoing http request to cloud services JCLOUDS-819 --- core/src/main/java/org/jclouds/Constants.java | 7 +++++++ .../org/jclouds/apis/internal/BaseApiMetadata.java | 6 ++++++ .../internal/JavaUrlHttpCommandExecutorService.java | 13 ++++++------- .../TrackingJavaUrlHttpCommandExecutorService.java | 6 ++++-- .../ApacheHCHttpCommandExecutorService.java | 11 ++++++++++- .../http/okhttp/OkHttpCommandExecutorService.java | 13 ++++++------- .../dynect/v3/config/DynECTHttpApiModule.java | 6 ++++-- ...StatusFromPayloadHttpCommandExecutorService.java | 7 +++++-- 8 files changed, 48 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/org/jclouds/Constants.java b/core/src/main/java/org/jclouds/Constants.java index f9d89f8361..388cc25700 100644 --- a/core/src/main/java/org/jclouds/Constants.java +++ b/core/src/main/java/org/jclouds/Constants.java @@ -339,6 +339,13 @@ public final class Constants { */ public static final String PROPERTY_STRIP_EXPECT_HEADER = "jclouds.strip-expect-header"; + /** + * String property. + *

+ * This will override the user agent header in http request. + */ + public static final String PROPERTY_USER_AGENT = "jclouds.user-agent"; + /** * When true, add the Connection: close header. Useful when interacting with * providers that don't properly support persistent connections. Defaults to false. diff --git a/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java b/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java index e516e2361d..e074a6c125 100644 --- a/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java +++ b/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java @@ -33,6 +33,7 @@ import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; import static org.jclouds.Constants.PROPERTY_SO_TIMEOUT; import static org.jclouds.Constants.PROPERTY_STRIP_EXPECT_HEADER; import static org.jclouds.Constants.PROPERTY_USER_THREADS; +import static org.jclouds.Constants.PROPERTY_USER_AGENT; import static org.jclouds.reflect.Reflection2.typeToken; import java.net.URI; @@ -40,6 +41,7 @@ import java.util.Properties; import java.util.Set; import org.jclouds.Context; +import org.jclouds.JcloudsVersion; import org.jclouds.View; import org.jclouds.apis.ApiMetadata; @@ -75,6 +77,10 @@ public abstract class BaseApiMetadata implements ApiMetadata { props.setProperty(PROPERTY_SESSION_INTERVAL, 60 + ""); props.setProperty(PROPERTY_PRETTY_PRINT_PAYLOADS, "true"); props.setProperty(PROPERTY_STRIP_EXPECT_HEADER, "false"); + props.setProperty(PROPERTY_USER_AGENT, + String.format("jclouds/%s java/%s", + JcloudsVersion.get(), + System.getProperty("java.version"))); props.setProperty(PROPERTY_CONNECTION_CLOSE_HEADER, "false"); // By default, we allow maximum parallel deletes to be equal to the number diff --git a/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java b/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java index 468f500db7..f64f4a797e 100644 --- a/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java +++ b/core/src/main/java/org/jclouds/http/internal/JavaUrlHttpCommandExecutorService.java @@ -22,6 +22,7 @@ import static com.google.common.net.HttpHeaders.CONTENT_LENGTH; import static com.google.common.net.HttpHeaders.HOST; import static com.google.common.net.HttpHeaders.USER_AGENT; import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; +import static org.jclouds.Constants.PROPERTY_USER_AGENT; import static org.jclouds.http.HttpUtils.filterOutContentHeaders; import static org.jclouds.io.Payloads.newInputStreamPayload; import static org.jclouds.util.Closeables2.closeQuietly; @@ -43,7 +44,6 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; -import org.jclouds.JcloudsVersion; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpUtils; @@ -64,22 +64,20 @@ import com.google.inject.Inject; @Singleton public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorService { - - public static final String DEFAULT_USER_AGENT = String.format("jclouds/%s java/%s", JcloudsVersion.get(), - System.getProperty("java.version")); - protected final Supplier untrustedSSLContextProvider; protected final Function proxyForURI; protected final HostnameVerifier verifier; @Inject(optional = true) protected Supplier sslContextSupplier; + protected final String userAgent; @Inject public JavaUrlHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec, DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler, DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier, @Named("untrusted") Supplier untrustedSSLContextProvider, Function proxyForURI, - @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods) { + @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods, + @Named(PROPERTY_USER_AGENT) String userAgent) { super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, idempotentMethods); if (utils.getMaxConnections() > 0) { System.setProperty("http.maxConnections", String.valueOf(checkNotNull(utils, "utils").getMaxConnections())); @@ -87,6 +85,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe this.untrustedSSLContextProvider = checkNotNull(untrustedSSLContextProvider, "untrustedSSLContextProvider"); this.verifier = checkNotNull(verifier, "verifier"); this.proxyForURI = checkNotNull(proxyForURI, "proxyForURI"); + this.userAgent = userAgent; } @Override @@ -149,7 +148,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe } connection.setRequestProperty(HOST, host); if (connection.getRequestProperty(USER_AGENT) == null) { - connection.setRequestProperty(USER_AGENT, DEFAULT_USER_AGENT); + connection.setRequestProperty(USER_AGENT, userAgent); } Payload payload = request.getPayload(); if (payload != null) { diff --git a/core/src/test/java/org/jclouds/http/internal/TrackingJavaUrlHttpCommandExecutorService.java b/core/src/test/java/org/jclouds/http/internal/TrackingJavaUrlHttpCommandExecutorService.java index 65cd854554..35fe0ef67f 100644 --- a/core/src/test/java/org/jclouds/http/internal/TrackingJavaUrlHttpCommandExecutorService.java +++ b/core/src/test/java/org/jclouds/http/internal/TrackingJavaUrlHttpCommandExecutorService.java @@ -17,6 +17,7 @@ package org.jclouds.http.internal; import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; +import static org.jclouds.Constants.PROPERTY_USER_AGENT; import java.net.Proxy; import java.net.URI; @@ -90,10 +91,11 @@ public class TrackingJavaUrlHttpCommandExecutorService extends JavaUrlHttpComman DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier, @Named("untrusted") Supplier untrustedSSLContextProvider, Function proxyForURI, List commandsInvoked, - @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods) + @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods, + @Named(PROPERTY_USER_AGENT) String userAgent) throws SecurityException, NoSuchFieldException { super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier, - untrustedSSLContextProvider, proxyForURI, idempotentMethods); + untrustedSSLContextProvider, proxyForURI, idempotentMethods, userAgent); this.commandsInvoked = commandsInvoked; } diff --git a/drivers/apachehc/src/main/java/org/jclouds/http/apachehc/ApacheHCHttpCommandExecutorService.java b/drivers/apachehc/src/main/java/org/jclouds/http/apachehc/ApacheHCHttpCommandExecutorService.java index cfca7ca7ef..3ef7af99c5 100644 --- a/drivers/apachehc/src/main/java/org/jclouds/http/apachehc/ApacheHCHttpCommandExecutorService.java +++ b/drivers/apachehc/src/main/java/org/jclouds/http/apachehc/ApacheHCHttpCommandExecutorService.java @@ -19,6 +19,7 @@ package org.jclouds.http.apachehc; import static com.google.common.hash.Hashing.md5; import static com.google.common.io.BaseEncoding.base64; import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; +import static org.jclouds.Constants.PROPERTY_USER_AGENT; import static org.jclouds.http.HttpUtils.filterOutContentHeaders; import java.io.IOException; @@ -28,6 +29,7 @@ import javax.inject.Inject; import javax.inject.Named; import org.apache.http.Header; +import org.apache.http.HttpHeaders; import org.apache.http.HttpHost; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; @@ -54,15 +56,18 @@ import com.google.common.collect.Multimap; public class ApacheHCHttpCommandExecutorService extends BaseHttpCommandExecutorService { private final HttpClient client; private final ApacheHCUtils apacheHCUtils; + private final String userAgent; @Inject ApacheHCHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec, DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler, DelegatingErrorHandler errorHandler, HttpWire wire, HttpClient client, - @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods) { + @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods, + @Named(PROPERTY_USER_AGENT) String userAgent) { super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, idempotentMethods); this.client = client; this.apacheHCUtils = new ApacheHCUtils(contentMetadataCodec); + this.userAgent = userAgent; } @Override @@ -73,6 +78,10 @@ public class ApacheHCHttpCommandExecutorService extends BaseHttpCommandExecutorS returnVal.addHeader("Content-MD5", md5); } + if (!returnVal.containsHeader(HttpHeaders.USER_AGENT)) { + returnVal.addHeader(HttpHeaders.USER_AGENT, userAgent); + } + return returnVal; } diff --git a/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java b/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java index f3e4ed07da..ddf62c1451 100644 --- a/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java +++ b/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.net.HttpHeaders.ACCEPT; import static com.google.common.net.HttpHeaders.USER_AGENT; import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; +import static org.jclouds.Constants.PROPERTY_USER_AGENT; import static org.jclouds.http.HttpUtils.filterOutContentHeaders; import static org.jclouds.io.Payloads.newInputStreamPayload; @@ -34,7 +35,6 @@ import okio.BufferedSink; import okio.Okio; import okio.Source; -import org.jclouds.JcloudsVersion; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpUtils; @@ -59,21 +59,20 @@ import com.squareup.okhttp.RequestBody; import com.squareup.okhttp.Response; public final class OkHttpCommandExecutorService extends BaseHttpCommandExecutorService { - - private static final String DEFAULT_USER_AGENT = String.format("jclouds-okhttp/%s java/%s", JcloudsVersion.get(), - System.getProperty("java.version")); - private final Function proxyForURI; private final OkHttpClient globalClient; + private final String userAgent; @Inject OkHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec, DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler, DelegatingErrorHandler errorHandler, HttpWire wire, Function proxyForURI, OkHttpClient okHttpClient, - @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods) { + @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods, + @Named(PROPERTY_USER_AGENT) String userAgent) { super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, idempotentMethods); this.proxyForURI = proxyForURI; this.globalClient = okHttpClient; + this.userAgent = userAgent; } @Override @@ -105,7 +104,7 @@ public final class OkHttpCommandExecutorService extends BaseHttpCommandExecutorS builder.addHeader(ACCEPT, "*/*"); } if (request.getFirstHeaderOrNull(USER_AGENT) == null) { - builder.addHeader(USER_AGENT, DEFAULT_USER_AGENT); + builder.addHeader(USER_AGENT, userAgent); } for (Map.Entry entry : request.getHeaders().entries()) { builder.addHeader(entry.getKey(), entry.getValue()); diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/config/DynECTHttpApiModule.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/config/DynECTHttpApiModule.java index bfc12a71c4..a4ca1944c3 100644 --- a/providers/dynect/src/main/java/org/jclouds/dynect/v3/config/DynECTHttpApiModule.java +++ b/providers/dynect/src/main/java/org/jclouds/dynect/v3/config/DynECTHttpApiModule.java @@ -17,6 +17,7 @@ package org.jclouds.dynect.v3.config; import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; +import static org.jclouds.Constants.PROPERTY_USER_AGENT; import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; import static org.jclouds.rest.config.BinderUtils.bindHttpApi; @@ -104,10 +105,11 @@ public class DynECTHttpApiModule extends HttpApiModule { DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler, DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier, @Named("untrusted") Supplier untrustedSSLContextProvider, Function proxyForURI, - @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods) + @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods, + @Named(PROPERTY_USER_AGENT) String userAgent) throws SecurityException, NoSuchFieldException { super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier, - untrustedSSLContextProvider, proxyForURI, idempotentMethods); + untrustedSSLContextProvider, proxyForURI, idempotentMethods, userAgent); } /** diff --git a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java index 4887c134b0..8b0f47d83d 100644 --- a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java +++ b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java @@ -17,6 +17,7 @@ package org.jclouds.profitbricks.http; import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; +import static org.jclouds.Constants.PROPERTY_USER_AGENT; import static org.jclouds.util.Closeables2.closeQuietly; import java.io.ByteArrayInputStream; @@ -69,8 +70,10 @@ public class ResponseStatusFromPayloadHttpCommandExecutorService extends JavaUrl DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier, @Named("untrusted") Supplier untrustedSSLContextProvider, Function proxyForURI, ParseSax faultHandler, - @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods) { - super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier, untrustedSSLContextProvider, proxyForURI, idempotentMethods); + @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods, + @Named(PROPERTY_USER_AGENT) String userAgent) { + super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier, untrustedSSLContextProvider, proxyForURI, + idempotentMethods, userAgent); this.faultHandler = faultHandler; }