use of com.amazonaws.AmazonWebServiceResponse 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.AmazonWebServiceResponse in project aws-sdk-android by aws-amplify.
the class StaxResponseHandler method handle.
/**
* @see com.amazonaws.http.HttpResponseHandler#handle(com.amazonaws.http.HttpResponse)
*/
@Override
public AmazonWebServiceResponse<T> handle(HttpResponse response) throws Exception {
log.trace("Parsing service response XML");
InputStream content = response.getContent();
if (content == null)
content = new ByteArrayInputStream("<eof/>".getBytes(StringUtils.UTF8));
XmlPullParser xpp = XML_PULL_PARSER_FACTORY.newPullParser();
xpp.setInput(content, null);
AmazonWebServiceResponse<T> awsResponse = new AmazonWebServiceResponse<T>();
StaxUnmarshallerContext unmarshallerContext = new StaxUnmarshallerContext(xpp, response.getHeaders());
unmarshallerContext.registerMetadataExpression("ResponseMetadata/RequestId", 2, ResponseMetadata.AWS_REQUEST_ID);
unmarshallerContext.registerMetadataExpression("requestId", 2, ResponseMetadata.AWS_REQUEST_ID);
registerAdditionalMetadataExpressions(unmarshallerContext);
T result = responseUnmarshaller.unmarshall(unmarshallerContext);
awsResponse.setResult(result);
Map<String, String> metadata = unmarshallerContext.getMetadata();
Map<String, String> responseHeaders = response.getHeaders();
if (responseHeaders != null) {
if (responseHeaders.get("x-amzn-RequestId") != null) {
metadata.put(ResponseMetadata.AWS_REQUEST_ID, responseHeaders.get("x-amzn-RequestId"));
}
}
awsResponse.setResponseMetadata(new ResponseMetadata(metadata));
log.trace("Done parsing service response");
return awsResponse;
}
use of com.amazonaws.AmazonWebServiceResponse in project aws-sdk-android by aws-amplify.
the class AmazonHttpClientTest method testRetryIOExceptionFromHandler.
@Test
@SuppressWarnings("unchecked")
public void testRetryIOExceptionFromHandler() throws Exception {
final IOException exception = new IOException("BOOM");
HttpResponseHandler<AmazonWebServiceResponse<Object>> handler = EasyMock.createMock(HttpResponseHandler.class);
EasyMock.expect(handler.needsConnectionLeftOpen()).andReturn(false).anyTimes();
EasyMock.expect(handler.handle(EasyMock.<HttpResponse>anyObject())).andThrow(exception).times(4);
HttpResponse response = HttpResponse.builder().content(new ByteArrayInputStream(new byte[0])).statusCode(200).statusText("OK").build();
EasyMock.expect(httpClient.execute(EasyMock.<HttpRequest>anyObject())).andReturn(response).times(4);
EasyMock.replay(handler, httpClient);
ExecutionContext context = new ExecutionContext();
Request<?> request = new DefaultRequest<Object>("testsvc");
request.setEndpoint(java.net.URI.create("http://testsvc.region.amazonaws.com"));
request.addHeader(HttpHeader.CONTENT_LENGTH, "0");
request.setContent(new java.io.ByteArrayInputStream(new byte[0]));
try {
client.execute(request, handler, null, context);
fail("No exception when request repeatedly fails!");
} catch (AmazonClientException e) {
assertSame(exception, e.getCause());
}
// Verify that we called execute 4 times.
EasyMock.verify(httpClient);
}
use of com.amazonaws.AmazonWebServiceResponse in project aws-sdk-android by aws-amplify.
the class HeadBucketResultHandler method handle.
@Override
public AmazonWebServiceResponse<HeadBucketResult> handle(HttpResponse response) throws Exception {
final AmazonWebServiceResponse<HeadBucketResult> awsResponse = new AmazonWebServiceResponse<HeadBucketResult>();
final HeadBucketResult result = new HeadBucketResult();
result.setBucketRegion(response.getHeaders().get(Headers.S3_BUCKET_REGION));
awsResponse.setResult(result);
return awsResponse;
}
Aggregations