Search in sources :

Example 6 with AmazonWebServiceResponse

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) */
}
Also used : AWSRequestMetrics(com.amazonaws.util.AWSRequestMetrics) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) InputStream(java.io.InputStream) AmazonClientException(com.amazonaws.AmazonClientException) IOException(java.io.IOException) URI(java.net.URI) AWSCredentials(com.amazonaws.auth.AWSCredentials) LinkedHashMap(java.util.LinkedHashMap) Signer(com.amazonaws.auth.Signer) AmazonWebServiceResponse(com.amazonaws.AmazonWebServiceResponse) Response(com.amazonaws.Response) AmazonServiceException(com.amazonaws.AmazonServiceException)

Example 7 with AmazonWebServiceResponse

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;
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) StaxUnmarshallerContext(com.amazonaws.transform.StaxUnmarshallerContext) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) XmlPullParser(org.xmlpull.v1.XmlPullParser) AmazonWebServiceResponse(com.amazonaws.AmazonWebServiceResponse) ResponseMetadata(com.amazonaws.ResponseMetadata)

Example 8 with AmazonWebServiceResponse

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);
}
Also used : DefaultRequest(com.amazonaws.DefaultRequest) ByteArrayInputStream(java.io.ByteArrayInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) AmazonClientException(com.amazonaws.AmazonClientException) IOException(java.io.IOException) AmazonWebServiceResponse(com.amazonaws.AmazonWebServiceResponse) Test(org.junit.Test)

Example 9 with AmazonWebServiceResponse

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;
}
Also used : HeadBucketResult(com.amazonaws.services.s3.model.HeadBucketResult) AmazonWebServiceResponse(com.amazonaws.AmazonWebServiceResponse)

Aggregations

AmazonWebServiceResponse (com.amazonaws.AmazonWebServiceResponse)9 ByteArrayInputStream (java.io.ByteArrayInputStream)4 InputStream (java.io.InputStream)4 Test (org.junit.Test)4 DefaultRequest (com.amazonaws.DefaultRequest)3 IOException (java.io.IOException)3 HashMap (java.util.HashMap)3 AmazonClientException (com.amazonaws.AmazonClientException)2 ResponseMetadata (com.amazonaws.ResponseMetadata)2 AWSCredentials (com.amazonaws.auth.AWSCredentials)2 Signer (com.amazonaws.auth.Signer)2 AWSRequestMetrics (com.amazonaws.util.AWSRequestMetrics)2 URI (java.net.URI)2 ArrayList (java.util.ArrayList)2 Capture (org.easymock.Capture)2 AmazonServiceException (com.amazonaws.AmazonServiceException)1 AmazonWebServiceRequest (com.amazonaws.AmazonWebServiceRequest)1 Response (com.amazonaws.Response)1 AnonymousAWSCredentials (com.amazonaws.auth.AnonymousAWSCredentials)1 HttpResponse (com.amazonaws.http.HttpResponse)1