com.google.cloud.http.HttpTransportOptions Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of google-cloud-core-http Show documentation
Show all versions of google-cloud-core-http Show documentation
Core http module for the google-cloud.
/*
* Copyright 2016 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.cloud.http;
import static com.google.common.base.MoreObjects.firstNonNull;
import com.google.api.client.extensions.appengine.http.UrlFetchTransport;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.gax.core.GaxProperties;
import com.google.api.gax.httpjson.HttpHeadersUtils;
import com.google.api.gax.httpjson.HttpJsonStatusCode;
import com.google.api.gax.rpc.ApiClientHeaderProvider;
import com.google.api.gax.rpc.EndpointContext;
import com.google.api.gax.rpc.HeaderProvider;
import com.google.api.gax.rpc.StatusCode;
import com.google.api.gax.rpc.UnauthenticatedException;
import com.google.auth.Credentials;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.http.HttpTransportFactory;
import com.google.cloud.NoCredentials;
import com.google.cloud.PlatformInformation;
import com.google.cloud.ServiceOptions;
import com.google.cloud.TransportOptions;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Objects;
/** Class representing service options for those services that use HTTP as the transport layer. */
public class HttpTransportOptions implements TransportOptions {
private static final long serialVersionUID = 7890117765045419810L;
private final int connectTimeout;
private final int readTimeout;
private final String httpTransportFactoryClassName;
private transient HttpTransportFactory httpTransportFactory;
public static class DefaultHttpTransportFactory implements HttpTransportFactory {
private static final HttpTransportFactory INSTANCE = new DefaultHttpTransportFactory();
@Override
public HttpTransport create() {
// Consider App Engine Standard
if (PlatformInformation.isOnGAEStandard7()) {
try {
return new UrlFetchTransport();
} catch (Exception ignore) {
// Maybe not on App Engine
}
}
return new NetHttpTransport();
}
}
/** Builder for {@code HttpTransportOptions}. */
public static class Builder {
private HttpTransportFactory httpTransportFactory;
private int connectTimeout = -1;
private int readTimeout = -1;
private Builder() {}
private Builder(HttpTransportOptions options) {
httpTransportFactory = options.httpTransportFactory;
connectTimeout = options.connectTimeout;
readTimeout = options.readTimeout;
}
public HttpTransportOptions build() {
return new HttpTransportOptions(this);
}
/**
* Sets the HTTP transport factory.
*
* @return the builder
*/
public Builder setHttpTransportFactory(HttpTransportFactory httpTransportFactory) {
this.httpTransportFactory = httpTransportFactory;
return this;
}
/**
* Sets the timeout in milliseconds to establish a connection.
*
* @param connectTimeout connection timeout in milliseconds. 0 for an infinite timeout, a
* negative number for the default value (20000).
* @return the builder
*/
public Builder setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
return this;
}
/**
* Sets the timeout in milliseconds to read data from an established connection.
*
* @param readTimeout read timeout in milliseconds. 0 for an infinite timeout, a negative number
* for the default value (20000).
* @return the builder
*/
public Builder setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
return this;
}
}
public HttpTransportOptions(Builder builder) {
httpTransportFactory =
firstNonNull(
builder.httpTransportFactory,
ServiceOptions.getFromServiceLoader(
HttpTransportFactory.class, DefaultHttpTransportFactory.INSTANCE));
httpTransportFactoryClassName = httpTransportFactory.getClass().getName();
connectTimeout = builder.connectTimeout;
readTimeout = builder.readTimeout;
}
/** Returns the HTTP transport factory. */
public HttpTransportFactory getHttpTransportFactory() {
return httpTransportFactory;
}
/**
* Returns a request initializer responsible for initializing requests according to service
* options.
*/
public HttpRequestInitializer getHttpRequestInitializer(
final ServiceOptions, ?> serviceOptions) {
Credentials scopedCredentials = serviceOptions.getScopedCredentials();
final HttpRequestInitializer delegate =
scopedCredentials != null && scopedCredentials != NoCredentials.getInstance()
? new HttpCredentialsAdapter(scopedCredentials)
: null;
HeaderProvider internalHeaderProvider =
getInternalHeaderProviderBuilder(serviceOptions).build();
final HeaderProvider headerProvider =
serviceOptions.getMergedHeaderProvider(internalHeaderProvider);
return new HttpRequestInitializer() {
/**
* Helper method to resolve the Universe Domain. First checks the user configuration from
* ServiceOptions, then the Environment Variable. If both haven't been set, resolve the value
* to be the Google Default Universe.
*/
private String determineUniverseDomain() {
String universeDomain = serviceOptions.getUniverseDomain();
if (universeDomain == null) {
universeDomain = System.getenv(EndpointContext.GOOGLE_CLOUD_UNIVERSE_DOMAIN);
}
return universeDomain == null ? Credentials.GOOGLE_DEFAULT_UNIVERSE : universeDomain;
}
@Override
public void initialize(HttpRequest httpRequest) throws IOException {
String configuredUniverseDomain = determineUniverseDomain();
// Default to the GDU. Override with value in the Credentials if needed
String credentialsUniverseDomain = Credentials.GOOGLE_DEFAULT_UNIVERSE;
// delegate is always HttpCredentialsAdapter or null (NoCredentials)
if (delegate != null) {
HttpCredentialsAdapter httpCredentialsAdapter = (HttpCredentialsAdapter) delegate;
credentialsUniverseDomain = httpCredentialsAdapter.getCredentials().getUniverseDomain();
}
// Validate the universe domain before initializing the request
if (!configuredUniverseDomain.equals(credentialsUniverseDomain)) {
throw new UnauthenticatedException(
new Throwable(
String.format(
EndpointContext.INVALID_UNIVERSE_DOMAIN_ERROR_TEMPLATE,
configuredUniverseDomain,
credentialsUniverseDomain)),
HttpJsonStatusCode.of(StatusCode.Code.UNAUTHENTICATED),
false);
}
if (delegate != null) {
delegate.initialize(httpRequest);
}
if (connectTimeout >= 0) {
httpRequest.setConnectTimeout(connectTimeout);
}
if (readTimeout >= 0) {
httpRequest.setReadTimeout(readTimeout);
}
HttpHeadersUtils.setHeaders(httpRequest.getHeaders(), headerProvider.getHeaders());
}
};
}
ApiClientHeaderProvider.Builder getInternalHeaderProviderBuilder(
ServiceOptions, ?> serviceOptions) {
ApiClientHeaderProvider.Builder builder = ApiClientHeaderProvider.newBuilder();
builder.setClientLibToken(
ServiceOptions.getGoogApiClientLibName(),
GaxProperties.getLibraryVersion(serviceOptions.getClass()));
builder.setQuotaProjectIdToken(serviceOptions.getQuotaProjectId());
return builder;
}
/**
* Returns the timeout in milliseconds to establish a connection. 0 is an infinite timeout, a
* negative number is the default value (20000).
*/
public int getConnectTimeout() {
return connectTimeout;
}
/**
* Returns the timeout in milliseconds to read from an established connection. 0 is an infinite
* timeout, a negative number is the default value (20000).
*/
public int getReadTimeout() {
return readTimeout;
}
public Builder toBuilder() {
return new Builder(this);
}
@Override
public int hashCode() {
return Objects.hash(httpTransportFactoryClassName, connectTimeout, readTimeout);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
HttpTransportOptions other = (HttpTransportOptions) obj;
return Objects.equals(httpTransportFactoryClassName, other.httpTransportFactoryClassName)
&& Objects.equals(connectTimeout, other.connectTimeout)
&& Objects.equals(readTimeout, other.readTimeout);
}
private void readObject(ObjectInputStream input) throws IOException, ClassNotFoundException {
input.defaultReadObject();
httpTransportFactory = ServiceOptions.newInstance(httpTransportFactoryClassName);
}
public static Builder newBuilder() {
return new Builder();
}
}