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
This commit is contained in:
Vijay Panghal 2016-12-15 11:04:02 -08:00 committed by Ignasi Barrera
parent fa746ff162
commit 79ad45d6b9
8 changed files with 48 additions and 21 deletions

View File

@ -339,6 +339,13 @@ public final class Constants {
*/ */
public static final String PROPERTY_STRIP_EXPECT_HEADER = "jclouds.strip-expect-header"; public static final String PROPERTY_STRIP_EXPECT_HEADER = "jclouds.strip-expect-header";
/**
* String property.
* <p/>
* 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 * When true, add the Connection: close header. Useful when interacting with
* providers that don't properly support persistent connections. Defaults to false. * providers that don't properly support persistent connections. Defaults to false.

View File

@ -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_SO_TIMEOUT;
import static org.jclouds.Constants.PROPERTY_STRIP_EXPECT_HEADER; import static org.jclouds.Constants.PROPERTY_STRIP_EXPECT_HEADER;
import static org.jclouds.Constants.PROPERTY_USER_THREADS; import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import static org.jclouds.Constants.PROPERTY_USER_AGENT;
import static org.jclouds.reflect.Reflection2.typeToken; import static org.jclouds.reflect.Reflection2.typeToken;
import java.net.URI; import java.net.URI;
@ -40,6 +41,7 @@ import java.util.Properties;
import java.util.Set; import java.util.Set;
import org.jclouds.Context; import org.jclouds.Context;
import org.jclouds.JcloudsVersion;
import org.jclouds.View; import org.jclouds.View;
import org.jclouds.apis.ApiMetadata; import org.jclouds.apis.ApiMetadata;
@ -75,6 +77,10 @@ public abstract class BaseApiMetadata implements ApiMetadata {
props.setProperty(PROPERTY_SESSION_INTERVAL, 60 + ""); props.setProperty(PROPERTY_SESSION_INTERVAL, 60 + "");
props.setProperty(PROPERTY_PRETTY_PRINT_PAYLOADS, "true"); props.setProperty(PROPERTY_PRETTY_PRINT_PAYLOADS, "true");
props.setProperty(PROPERTY_STRIP_EXPECT_HEADER, "false"); 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"); props.setProperty(PROPERTY_CONNECTION_CLOSE_HEADER, "false");
// By default, we allow maximum parallel deletes to be equal to the number // By default, we allow maximum parallel deletes to be equal to the number

View File

@ -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.HOST;
import static com.google.common.net.HttpHeaders.USER_AGENT; import static com.google.common.net.HttpHeaders.USER_AGENT;
import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; 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.http.HttpUtils.filterOutContentHeaders;
import static org.jclouds.io.Payloads.newInputStreamPayload; import static org.jclouds.io.Payloads.newInputStreamPayload;
import static org.jclouds.util.Closeables2.closeQuietly; 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.HttpsURLConnection;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import org.jclouds.JcloudsVersion;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
@ -64,22 +64,20 @@ import com.google.inject.Inject;
@Singleton @Singleton
public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorService<HttpURLConnection> { public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorService<HttpURLConnection> {
public static final String DEFAULT_USER_AGENT = String.format("jclouds/%s java/%s", JcloudsVersion.get(),
System.getProperty("java.version"));
protected final Supplier<SSLContext> untrustedSSLContextProvider; protected final Supplier<SSLContext> untrustedSSLContextProvider;
protected final Function<URI, Proxy> proxyForURI; protected final Function<URI, Proxy> proxyForURI;
protected final HostnameVerifier verifier; protected final HostnameVerifier verifier;
@Inject(optional = true) @Inject(optional = true)
protected Supplier<SSLContext> sslContextSupplier; protected Supplier<SSLContext> sslContextSupplier;
protected final String userAgent;
@Inject @Inject
public JavaUrlHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec, public JavaUrlHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler, DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier, DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier,
@Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, Function<URI, Proxy> proxyForURI, @Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, Function<URI, Proxy> 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); super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, idempotentMethods);
if (utils.getMaxConnections() > 0) { if (utils.getMaxConnections() > 0) {
System.setProperty("http.maxConnections", String.valueOf(checkNotNull(utils, "utils").getMaxConnections())); 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.untrustedSSLContextProvider = checkNotNull(untrustedSSLContextProvider, "untrustedSSLContextProvider");
this.verifier = checkNotNull(verifier, "verifier"); this.verifier = checkNotNull(verifier, "verifier");
this.proxyForURI = checkNotNull(proxyForURI, "proxyForURI"); this.proxyForURI = checkNotNull(proxyForURI, "proxyForURI");
this.userAgent = userAgent;
} }
@Override @Override
@ -149,7 +148,7 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
} }
connection.setRequestProperty(HOST, host); connection.setRequestProperty(HOST, host);
if (connection.getRequestProperty(USER_AGENT) == null) { if (connection.getRequestProperty(USER_AGENT) == null) {
connection.setRequestProperty(USER_AGENT, DEFAULT_USER_AGENT); connection.setRequestProperty(USER_AGENT, userAgent);
} }
Payload payload = request.getPayload(); Payload payload = request.getPayload();
if (payload != null) { if (payload != null) {

View File

@ -17,6 +17,7 @@
package org.jclouds.http.internal; package org.jclouds.http.internal;
import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS;
import static org.jclouds.Constants.PROPERTY_USER_AGENT;
import java.net.Proxy; import java.net.Proxy;
import java.net.URI; import java.net.URI;
@ -90,10 +91,11 @@ public class TrackingJavaUrlHttpCommandExecutorService extends JavaUrlHttpComman
DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier, DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier,
@Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, Function<URI, Proxy> proxyForURI, @Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, Function<URI, Proxy> proxyForURI,
List<HttpCommand> commandsInvoked, List<HttpCommand> commandsInvoked,
@Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods) @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods,
@Named(PROPERTY_USER_AGENT) String userAgent)
throws SecurityException, NoSuchFieldException { throws SecurityException, NoSuchFieldException {
super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier, super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier,
untrustedSSLContextProvider, proxyForURI, idempotentMethods); untrustedSSLContextProvider, proxyForURI, idempotentMethods, userAgent);
this.commandsInvoked = commandsInvoked; this.commandsInvoked = commandsInvoked;
} }

View File

@ -19,6 +19,7 @@ package org.jclouds.http.apachehc;
import static com.google.common.hash.Hashing.md5; import static com.google.common.hash.Hashing.md5;
import static com.google.common.io.BaseEncoding.base64; import static com.google.common.io.BaseEncoding.base64;
import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; 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.http.HttpUtils.filterOutContentHeaders;
import java.io.IOException; import java.io.IOException;
@ -28,6 +29,7 @@ import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import org.apache.http.Header; import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
@ -54,15 +56,18 @@ import com.google.common.collect.Multimap;
public class ApacheHCHttpCommandExecutorService extends BaseHttpCommandExecutorService<HttpUriRequest> { public class ApacheHCHttpCommandExecutorService extends BaseHttpCommandExecutorService<HttpUriRequest> {
private final HttpClient client; private final HttpClient client;
private final ApacheHCUtils apacheHCUtils; private final ApacheHCUtils apacheHCUtils;
private final String userAgent;
@Inject @Inject
ApacheHCHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec, ApacheHCHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler, DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire, HttpClient client, 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); super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, idempotentMethods);
this.client = client; this.client = client;
this.apacheHCUtils = new ApacheHCUtils(contentMetadataCodec); this.apacheHCUtils = new ApacheHCUtils(contentMetadataCodec);
this.userAgent = userAgent;
} }
@Override @Override
@ -73,6 +78,10 @@ public class ApacheHCHttpCommandExecutorService extends BaseHttpCommandExecutorS
returnVal.addHeader("Content-MD5", md5); returnVal.addHeader("Content-MD5", md5);
} }
if (!returnVal.containsHeader(HttpHeaders.USER_AGENT)) {
returnVal.addHeader(HttpHeaders.USER_AGENT, userAgent);
}
return returnVal; return returnVal;
} }

View File

@ -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.ACCEPT;
import static com.google.common.net.HttpHeaders.USER_AGENT; import static com.google.common.net.HttpHeaders.USER_AGENT;
import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; 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.http.HttpUtils.filterOutContentHeaders;
import static org.jclouds.io.Payloads.newInputStreamPayload; import static org.jclouds.io.Payloads.newInputStreamPayload;
@ -34,7 +35,6 @@ import okio.BufferedSink;
import okio.Okio; import okio.Okio;
import okio.Source; import okio.Source;
import org.jclouds.JcloudsVersion;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
@ -59,21 +59,20 @@ import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response; import com.squareup.okhttp.Response;
public final class OkHttpCommandExecutorService extends BaseHttpCommandExecutorService<Request> { public final class OkHttpCommandExecutorService extends BaseHttpCommandExecutorService<Request> {
private static final String DEFAULT_USER_AGENT = String.format("jclouds-okhttp/%s java/%s", JcloudsVersion.get(),
System.getProperty("java.version"));
private final Function<URI, Proxy> proxyForURI; private final Function<URI, Proxy> proxyForURI;
private final OkHttpClient globalClient; private final OkHttpClient globalClient;
private final String userAgent;
@Inject @Inject
OkHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec, OkHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler, DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire, Function<URI, Proxy> proxyForURI, OkHttpClient okHttpClient, DelegatingErrorHandler errorHandler, HttpWire wire, Function<URI, Proxy> 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); super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, idempotentMethods);
this.proxyForURI = proxyForURI; this.proxyForURI = proxyForURI;
this.globalClient = okHttpClient; this.globalClient = okHttpClient;
this.userAgent = userAgent;
} }
@Override @Override
@ -105,7 +104,7 @@ public final class OkHttpCommandExecutorService extends BaseHttpCommandExecutorS
builder.addHeader(ACCEPT, "*/*"); builder.addHeader(ACCEPT, "*/*");
} }
if (request.getFirstHeaderOrNull(USER_AGENT) == null) { if (request.getFirstHeaderOrNull(USER_AGENT) == null) {
builder.addHeader(USER_AGENT, DEFAULT_USER_AGENT); builder.addHeader(USER_AGENT, userAgent);
} }
for (Map.Entry<String, String> entry : request.getHeaders().entries()) { for (Map.Entry<String, String> entry : request.getHeaders().entries()) {
builder.addHeader(entry.getKey(), entry.getValue()); builder.addHeader(entry.getKey(), entry.getValue());

View File

@ -17,6 +17,7 @@
package org.jclouds.dynect.v3.config; package org.jclouds.dynect.v3.config;
import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; 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.http.HttpUtils.closeClientButKeepContentStream;
import static org.jclouds.rest.config.BinderUtils.bindHttpApi; import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
@ -104,10 +105,11 @@ public class DynECTHttpApiModule extends HttpApiModule<DynECTApi> {
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler, DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier, DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier,
@Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, Function<URI, Proxy> proxyForURI, @Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, Function<URI, Proxy> proxyForURI,
@Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods) @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods,
@Named(PROPERTY_USER_AGENT) String userAgent)
throws SecurityException, NoSuchFieldException { throws SecurityException, NoSuchFieldException {
super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier, super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier,
untrustedSSLContextProvider, proxyForURI, idempotentMethods); untrustedSSLContextProvider, proxyForURI, idempotentMethods, userAgent);
} }
/** /**

View File

@ -17,6 +17,7 @@
package org.jclouds.profitbricks.http; package org.jclouds.profitbricks.http;
import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS;
import static org.jclouds.Constants.PROPERTY_USER_AGENT;
import static org.jclouds.util.Closeables2.closeQuietly; import static org.jclouds.util.Closeables2.closeQuietly;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -69,8 +70,10 @@ public class ResponseStatusFromPayloadHttpCommandExecutorService extends JavaUrl
DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier, DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier,
@Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, Function<URI, Proxy> proxyForURI, @Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, Function<URI, Proxy> proxyForURI,
ParseSax<ServiceFault> faultHandler, ParseSax<ServiceFault> faultHandler,
@Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods) { @Named(PROPERTY_IDEMPOTENT_METHODS) String idempotentMethods,
super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier, untrustedSSLContextProvider, proxyForURI, idempotentMethods); @Named(PROPERTY_USER_AGENT) String userAgent) {
super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier, untrustedSSLContextProvider, proxyForURI,
idempotentMethods, userAgent);
this.faultHandler = faultHandler; this.faultHandler = faultHandler;
} }