use of com.amazonaws.auth.Signer in project aws-sdk-android by aws-amplify.
the class AmazonWebServiceClient method setRegion.
/**
* An alternative to {@link AmazonWebServiceClient#setEndpoint(String)},
* sets the regional endpoint for this client's service calls. Callers can
* use this method to control which AWS region they want to work with.
* <p>
* <b>This method is not threadsafe. A region should be configured when the
* client is created and before any service requests are made. Changing it
* afterwards creates inevitable race conditions for any service requests in
* transit or retrying.</b>
* <p>
* By default, all service endpoints in all regions use the https protocol.
* To use http instead, specify it in the {@link ClientConfiguration}
* supplied at construction.
*
* @param region The region this client will communicate with. See
* {@link Region#getRegion(com.amazonaws.regions.Regions)} for
* accessing a given region.
* @throws java.lang.IllegalArgumentException If the given region is null,
* or if this service isn't available in the given region. See
* {@link Region#isServiceSupported(String)}
* @see Region#getRegion(com.amazonaws.regions.Regions)
* @see Region#createClient(Class,
* com.amazonaws.auth.AWSCredentialsProvider, ClientConfiguration)
*/
@SuppressWarnings("checkstyle:hiddenfield")
public void setRegion(final Region region) {
if (region == null) {
throw new IllegalArgumentException("No region provided");
}
final String serviceName = getServiceNameIntern();
String serviceEndpoint;
if (region.isServiceSupported(serviceName)) {
serviceEndpoint = region.getServiceEndpoint(serviceName);
final int protocolIdx = serviceEndpoint.indexOf("://");
// Strip off the protocol to allow the client config to specify it
if (protocolIdx >= 0) {
serviceEndpoint = serviceEndpoint.substring(protocolIdx + "://".length());
}
} else {
serviceEndpoint = String.format("%s.%s.%s", getEndpointPrefix(), region.getName(), region.getDomain());
}
final URI uri = toURI(serviceEndpoint);
final Signer signer = computeSignerByServiceRegion(serviceName, region.getName(), signerRegionOverride, false);
synchronized (this) {
this.endpoint = uri;
this.signer = signer;
}
}
use of com.amazonaws.auth.Signer in project aws-sdk-android by aws-amplify.
the class AmazonWebServiceClient method setEndpoint.
/**
* Overrides the default endpoint for this client. Callers can use this
* method to control which AWS region they want to work with.
* <p>
* <b>This method is not threadsafe. Endpoints should be configured when the
* client is created and before any service requests are made. Changing it
* afterwards creates inevitable race conditions for any service requests in
* transit.</b>
* <p>
* Callers can pass in just the endpoint (ex: "ec2.amazonaws.com") or a full
* URL, including the protocol (ex: "https://ec2.amazonaws.com"). If the
* protocol is not specified here, the default protocol from this client's
* {@link ClientConfiguration} will be used, which by default is HTTPS.
* <p>
* For more information on using AWS regions with the AWS SDK for Java, and
* a complete list of all available endpoints for all AWS services, see:
* <a href= "https://docs.aws.amazon.com/general/latest/gr/rande.html">
* https://docs.aws.amazon.com/general/latest/gr/rande.html
* </a>
*
* @param endpoint The endpoint (ex: "ec2.amazonaws.com") or a full URL,
* including the protocol (ex: "https://ec2.amazonaws.com") of
* the region specific AWS endpoint this client will communicate
* with.
* @throws IllegalArgumentException If any problems are detected with the
* specified endpoint.
*/
public void setEndpoint(final String endpoint) {
final URI uri = toURI(endpoint);
@SuppressWarnings("checkstyle:hiddenfield") final Signer signer = computeSignerByURI(uri, signerRegionOverride, false);
synchronized (this) {
this.endpoint = uri;
this.signer = signer;
}
}
use of com.amazonaws.auth.Signer in project aws-sdk-android by aws-amplify.
the class AmazonHttpClient method executeHelper.
/**
* Internal method to execute the HTTP method given.
*
* @see AmazonHttpClient#execute(Request, HttpResponseHandler,
* HttpResponseHandler, ExecutionContext)
*/
@SuppressWarnings("checkstyle:methodlength")
<T> Response<T> executeHelper(Request<?> request, HttpResponseHandler<AmazonWebServiceResponse<T>> responseHandler, HttpResponseHandler<AmazonServiceException> errorResponseHandler, ExecutionContext executionContext) {
/*
* Depending on which response handler we end up choosing to handle the
* HTTP response, it might require us to leave the underlying HTTP
* connection open, depending on whether or not it reads the complete
* HTTP response stream from the HTTP connection, or if delays reading
* any of the content until after a response is returned to the caller.
*/
boolean leaveHttpConnectionOpen = false;
final AWSRequestMetrics awsRequestMetrics = executionContext.getAwsRequestMetrics();
/*
* add the service endpoint to the logs. You can infer service name from
* service endpoint
*/
awsRequestMetrics.addProperty(Field.ServiceName, request.getServiceName());
awsRequestMetrics.addProperty(Field.ServiceEndpoint, request.getEndpoint());
// Apply whatever request options we know how to handle, such as
// user-agent.
setUserAgent(request);
request.addHeader(HEADER_SDK_TRANSACTION_ID, UUID.randomUUID().toString());
int requestCount = 0;
long lastBackoffDelay = 0;
URI redirectedURI = null;
AmazonClientException retriedException = null;
// Make a copy of the original request params and headers so that we can
// permute it in this loop and start over with the original every time.
final Map<String, String> originalParameters = new LinkedHashMap<String, String>(request.getParameters());
final Map<String, String> originalHeaders = new HashMap<String, String>(request.getHeaders());
// mark input stream if supported
final InputStream originalContent = request.getContent();
if (originalContent != null && originalContent.markSupported()) {
originalContent.mark(-1);
}
final AWSCredentials credentials = executionContext.getCredentials();
Signer signer = null;
HttpResponse httpResponse = null;
HttpRequest httpRequest = null;
while (true) {
++requestCount;
awsRequestMetrics.setCounter(Field.RequestCount, requestCount);
if (requestCount > 1) {
// retry
request.setParameters(originalParameters);
request.setHeaders(originalHeaders);
request.setContent(originalContent);
}
if (redirectedURI != null && request.getEndpoint() == null && request.getResourcePath() == null) {
request.setEndpoint(URI.create(redirectedURI.getScheme() + "://" + redirectedURI.getAuthority()));
request.setResourcePath(redirectedURI.getPath());
}
try {
if (requestCount > 1) {
// retry
awsRequestMetrics.startEvent(Field.RetryPauseTime);
try {
lastBackoffDelay = pauseBeforeNextRetry(request.getOriginalRequest(), retriedException, requestCount, config.getRetryPolicy());
} finally {
awsRequestMetrics.endEvent(Field.RetryPauseTime);
}
final InputStream content = request.getContent();
if (content != null && content.markSupported()) {
content.reset();
}
}
request.addHeader(HEADER_SDK_RETRY_INFO, (requestCount - 1) + "/" + lastBackoffDelay);
// Sign the request if a signer was provided
if (signer == null) {
signer = executionContext.getSignerByURI(request.getEndpoint());
}
if (signer != null && credentials != null) {
awsRequestMetrics.startEvent(Field.RequestSigningTime);
try {
signer.sign(request, credentials);
} finally {
awsRequestMetrics.endEvent(Field.RequestSigningTime);
}
}
if (REQUEST_LOG.isDebugEnabled()) {
REQUEST_LOG.debug("Sending Request: " + request.toString());
}
httpRequest = requestFactory.createHttpRequest(request, config, executionContext);
retriedException = null;
awsRequestMetrics.startEvent(Field.HttpRequestTime);
try {
httpResponse = httpClient.execute(httpRequest);
} finally {
awsRequestMetrics.endEvent(Field.HttpRequestTime);
}
if (isRequestSuccessful(httpResponse)) {
awsRequestMetrics.addProperty(Field.StatusCode, httpResponse.getStatusCode());
/*
* If we get back any 2xx status code, then we know we
* should treat the service call as successful.
*/
leaveHttpConnectionOpen = responseHandler.needsConnectionLeftOpen();
final T response = handleResponse(request, responseHandler, httpResponse, executionContext);
return new Response<T>(response, httpResponse);
} else if (isTemporaryRedirect(httpResponse)) {
/*
* S3 sends 307 Temporary Redirects if you try to delete an
* EU bucket from the US endpoint. If we get a 307, we'll
* point the HTTP method to the redirected location, and let
* the next retry deliver the request to the right location.
*/
final String redirectedLocation = httpResponse.getHeaders().get("Location");
log.debug("Redirecting to: " + redirectedLocation);
// set redirect uri and retry
redirectedURI = URI.create(redirectedLocation);
request.setEndpoint(null);
request.setResourcePath(null);
awsRequestMetrics.addProperty(Field.StatusCode, httpResponse.getStatusCode());
awsRequestMetrics.addProperty(Field.RedirectLocation, redirectedLocation);
awsRequestMetrics.addProperty(Field.AWSRequestID, null);
} else {
leaveHttpConnectionOpen = errorResponseHandler.needsConnectionLeftOpen();
final AmazonServiceException ase = handleErrorResponse(request, errorResponseHandler, httpResponse);
awsRequestMetrics.addProperty(Field.AWSRequestID, ase.getRequestId());
awsRequestMetrics.addProperty(Field.AWSErrorCode, ase.getErrorCode());
awsRequestMetrics.addProperty(Field.StatusCode, ase.getStatusCode());
if (!shouldRetry(request.getOriginalRequest(), httpRequest.getContent(), ase, requestCount, config.getRetryPolicy())) {
throw ase;
}
// Cache the retryable exception
retriedException = ase;
/*
* Checking for clock skew error again because we don't want
* to set the global time offset for every service
* exception.
*/
if (RetryUtils.isClockSkewError(ase)) {
final long timeOffset = parseClockSkewOffset(httpResponse, ase);
SDKGlobalConfiguration.setGlobalTimeOffset(timeOffset);
}
resetRequestAfterError(request, ase);
}
} catch (final IOException ioe) {
if (log.isDebugEnabled()) {
log.debug("Unable to execute HTTP request: " + ioe.getMessage(), ioe);
}
awsRequestMetrics.incrementCounter(Field.Exception);
awsRequestMetrics.addProperty(Field.Exception, ioe);
awsRequestMetrics.addProperty(Field.AWSRequestID, null);
final AmazonClientException ace = new AmazonClientException("Unable to execute HTTP request: " + ioe.getMessage(), ioe);
if (!shouldRetry(request.getOriginalRequest(), httpRequest.getContent(), ace, requestCount, config.getRetryPolicy())) {
throw ace;
}
// Cache the retryable exception
retriedException = ace;
resetRequestAfterError(request, ioe);
} catch (final RuntimeException e) {
throw handleUnexpectedFailure(e, awsRequestMetrics);
} catch (final Error e) {
throw handleUnexpectedFailure(e, awsRequestMetrics);
} finally {
/*
* Some response handlers need to manually manage the HTTP
* connection and will take care of releasing the connection on
* their own, but if this response handler doesn't need the
* connection left open, we go ahead and release the it to free
* up resources.
*/
if (!leaveHttpConnectionOpen && httpResponse != null) {
try {
if (httpResponse.getRawContent() != null) {
httpResponse.getRawContent().close();
}
} catch (final IOException e) {
log.warn("Cannot close the response content.", e);
}
}
}
}
/* end while (true) */
}
use of com.amazonaws.auth.Signer in project aws-sdk-android by aws-amplify.
the class AmazonS3Client method generatePresignedUrl.
/*
* (non-Javadoc)
* @see
* com.amazonaws.services.s3.AmazonS3#generatePresignedUrl(com.amazonaws
* .services.s3.model.GeneratePresignedUrlRequest)
*/
@Override
public URL generatePresignedUrl(GeneratePresignedUrlRequest generatePresignedUrlRequest) throws AmazonClientException {
assertParameterNotNull(generatePresignedUrlRequest, "The request parameter must be specified when generating a pre-signed URL");
final String bucketName = generatePresignedUrlRequest.getBucketName();
final String key = generatePresignedUrlRequest.getKey();
assertParameterNotNull(bucketName, "The bucket name parameter must be specified when generating a pre-signed URL");
assertParameterNotNull(generatePresignedUrlRequest.getMethod(), "The HTTP method request parameter must be specified when generating a pre-signed URL");
if (generatePresignedUrlRequest.getExpiration() == null) {
generatePresignedUrlRequest.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 15));
}
final HttpMethodName httpMethod = HttpMethodName.valueOf(generatePresignedUrlRequest.getMethod().toString());
// If the key starts with a slash character itself, the following method
// will actually add another slash before the resource path to prevent
// the HttpClient mistakenly treating the slash as a path delimiter.
// For presigned request, we need to remember to remove this extra slash
// before generating the URL.
final Request<GeneratePresignedUrlRequest> request = createRequest(bucketName, key, generatePresignedUrlRequest, httpMethod);
addParameterIfNotNull(request, "versionId", generatePresignedUrlRequest.getVersionId());
if (generatePresignedUrlRequest.isZeroByteContent()) {
request.setContent(new ByteArrayInputStream(new byte[0]));
}
for (final Entry<String, String> entry : generatePresignedUrlRequest.getRequestParameters().entrySet()) {
request.addParameter(entry.getKey(), entry.getValue());
}
if (generatePresignedUrlRequest.getContentType() != null) {
request.addHeader(Headers.CONTENT_TYPE, generatePresignedUrlRequest.getContentType());
}
if (generatePresignedUrlRequest.getContentMd5() != null) {
request.addHeader(Headers.CONTENT_MD5, generatePresignedUrlRequest.getContentMd5());
}
// SSE-C
populateSSE_C(request, generatePresignedUrlRequest.getSSECustomerKey());
// SSE
addHeaderIfNotNull(request, Headers.SERVER_SIDE_ENCRYPTION, generatePresignedUrlRequest.getSSEAlgorithm());
// SSE-KMS
addHeaderIfNotNull(request, Headers.SERVER_SIDE_ENCRYPTION_KMS_KEY_ID, generatePresignedUrlRequest.getKmsCmkId());
// Add custom query parameters
final Map<String, String> customQueryParameters = generatePresignedUrlRequest.getCustomQueryParameters();
if (customQueryParameters != null) {
for (Map.Entry<String, String> e : customQueryParameters.entrySet()) {
request.addParameter(e.getKey(), e.getValue());
}
}
addResponseHeaderParameters(request, generatePresignedUrlRequest.getResponseHeaders());
final Signer signer = createSigner(request, bucketName, key);
if (signer instanceof Presigner) {
// If we have a signer which knows how to presign requests,
// delegate directly to it.
((Presigner) signer).presignRequest(request, awsCredentialsProvider.getCredentials(), generatePresignedUrlRequest.getExpiration());
} else {
// Otherwise use the default presigning method, which is hardcoded
// to use QueryStringSigner.
presignRequest(request, generatePresignedUrlRequest.getMethod(), bucketName, key, generatePresignedUrlRequest.getExpiration(), null);
}
// Remove the leading slash (if any) in the resource-path
return ServiceUtils.convertRequestToUrl(request, true);
}
use of com.amazonaws.auth.Signer in project aws-sdk-android by aws-amplify.
the class AmazonS3Client method createSigner.
/**
* Returns a "complete" S3 specific signer, taking into the S3 bucket, key,
* and the current S3 client configuration into account.
*
* Signer = get a Signer based on the bucket endpoint // InternalConfig in CoreRuntime makes this decision
* [If the region is not specified, uses SigV2 signer,
* Else If the region is specified, and If the region only supports SigV4, then uses SigV4]
* If Signer is not Overriden {
* If Signer is a V4 Signer and Region is null
* Get the region from AmazonS3Client or BucketRegionCache
* If available
* Use SigV4
* Else If PresignedUrl
* Use SigV2
* If Signer Region is overriden
* Use SigV4
* If BucketRegionCache has a region
* Use SigV4
* }
*
* If Signer is SigV2 signer
* Use SigV2
*/
protected Signer createSigner(final Request<?> request, final String bucketName, final String key) {
// Instead of using request.getEndpoint() for this parameter, we use
// endpoint which is because
// in accelerate mode, the endpoint in request is regionless. We need
// the client-wide endpoint
// to fetch the region information and pick the correct signer.
final URI uri = clientOptions.isAccelerateModeEnabled() ? endpoint : request.getEndpoint();
// This method retrieves the signer based on the URI. Currently
// S3's default signer is a SigV2 signer implemented in S3Signer
final Signer signer = getSignerByURI(uri);
if (!isSignerOverridden()) {
if ((signer instanceof AWSS3V4Signer) && noExplicitRegionProvided(request)) {
final String region = clientRegion == null ? bucketRegionCache.get(bucketName) : clientRegion;
if (region != null) {
// If cache contains the region for the bucket, create an endpoint for the region and
// update the request with that endpoint.
resolveRequestEndpoint(request, bucketName, key, RuntimeHttpUtils.toUri(RegionUtils.getRegion(region).getServiceEndpoint(S3_SERVICE_NAME), clientConfiguration));
AWSS3V4Signer sigV4Signer = (AWSS3V4Signer) signer;
setAWSS3V4SignerWithServiceNameAndRegion((AWSS3V4Signer) signer, region);
return sigV4Signer;
} else if (request.getOriginalRequest() instanceof GeneratePresignedUrlRequest) {
return createSigV2Signer(request, bucketName, key);
}
}
// use the signer override if provided, else see if you can get the
// signer from bucketreqion cache.
final String regionOverride = getSignerRegionOverride() == null ? (clientRegion == null ? bucketRegionCache.get(bucketName) : clientRegion) : getSignerRegionOverride();
if (regionOverride != null) {
AWSS3V4Signer sigV4Signer = new AWSS3V4Signer();
setAWSS3V4SignerWithServiceNameAndRegion(sigV4Signer, regionOverride);
return sigV4Signer;
}
}
if (signer instanceof S3Signer) {
// new one with the appropriate values for this request.
return createSigV2Signer(request, bucketName, key);
}
return signer;
}
Aggregations