Beispiel #1
0
        /// <summary>
        /// Return true if the request should be retried. Implements additional checks
        /// specific to S3 on top of the checks in DefaultRetryPolicy.
        /// </summary>
        /// <param name="executionContext">Request context containing the state of the request.</param>
        /// <param name="exception">The exception thrown by the previous request.</param>
        /// <returns>Return true if the request should be retried.</returns>
        public override bool RetryForException(Runtime.IExecutionContext executionContext, Exception exception)
        {
            var serviceException = exception as AmazonServiceException;

            if (serviceException != null)
            {
                if (serviceException.StatusCode == HttpStatusCode.OK)
                {
                    var requestType = executionContext.RequestContext.OriginalRequest.GetType();
                    if (AmazonS3RetryPolicy.RequestsWith200Error.Contains(requestType))
                    {
                        // Retry on HTTP 200 responses which contain an error response.
                        // CopyObject, CopyPart and CompleteMultipartUpload operations can return this
                        // response.
                        return(true);
                    }
                }

                if (serviceException.StatusCode == HttpStatusCode.BadRequest)
                {
                    var configuredUri = new Uri(executionContext.RequestContext.ClientConfig.DetermineServiceURL());
                    if (configuredUri.Host.Equals(S3Constants.S3DefaultEndpoint) &&
                        (serviceException.Message.Contains(AWS4Signer.AWS4AlgorithmTag) ||
                         serviceException.Message.Contains(AWS_KMS_Signature_Error))
                        )
                    {
                        // If the response message indicates AWS4 signing should have been used,
                        // we've attempted to access a bucket in an AWS4-only region (e.g. EU Central (Frankfurt)) with an AWS2
                        // signature and/or client not configured with the correct region.
                        // Retry the request to the s3-external endpoint to yield a 307 redirect
                        // that we can then follow to the correct bucket location with the expected
                        // signing algorithm.
                        Logger.InfoFormat("Request {0}: the bucket you are attempting to access should be addressed using a region-specific endpoint."
                                          + " Additional calls will be made to attempt to determine the correct region to be used."
                                          + " For better performance configure your client to use the correct region.",
                                          executionContext.RequestContext.RequestName);

                        var r     = executionContext.RequestContext.Request;
                        var s3Uri = new AmazonS3Uri(r.Endpoint);

                        // since DNS resolved, yielding an auth error from the service,
                        // we're assuming we do not need to test (again) for dns compatibility
                        // on the bucket name
                        var tempEndpoint = string.Format(CultureInfo.InvariantCulture,
                                                         "https://{0}.{1}", s3Uri.Bucket, S3Constants.S3AlternateDefaultEndpoint);
                        r.Endpoint = new Uri(tempEndpoint);

                        if (serviceException.Message.Contains(AWS_KMS_Signature_Error))
                        {
                            r.UseSigV4             = true;
                            r.AuthenticationRegion = RegionEndpoint.USEast1.SystemName;
                            executionContext.RequestContext.IsSigned = false;
                        }
                        return(true);
                    }
                }
            }

            return(base.RetryForException(executionContext, exception));
        }
Beispiel #2
0
        internal static async Task <bool> SharedRetryForExceptionAsync(Runtime.IExecutionContext executionContext, Exception exception,
                                                                       Func <Runtime.IExecutionContext, Exception, bool?> retryForExceptionSync,
                                                                       Func <Runtime.IExecutionContext, Exception, bool> baseRetryForException)
        {
            var syncResult = retryForExceptionSync(executionContext, exception);

            if (syncResult.HasValue)
            {
                return(syncResult.Value);
            }
            else
            {
                var         serviceException = exception as AmazonServiceException;
                string      correctedRegion  = null;
                AmazonS3Uri s3BucketUri;
                if (AmazonS3Uri.TryParseAmazonS3Uri(executionContext.RequestContext.Request.Endpoint, out s3BucketUri))
                {
                    var credentials = executionContext.RequestContext.ImmutableCredentials;
                    correctedRegion = await BucketRegionDetector.DetectMismatchWithHeadBucketFallbackAsync(s3BucketUri, serviceException, credentials).ConfigureAwait(false);
                }

                if (correctedRegion == null)
                {
                    return(baseRetryForException(executionContext, exception));
                }
                else
                {
                    // change authentication region of request and signal the handler to sign again with the new region
                    executionContext.RequestContext.Request.AuthenticationRegion = correctedRegion;
                    executionContext.RequestContext.IsSigned = false;
                    return(true);
                }
            }
        }
        /// <summary>
        /// Return true if the request should be retried. Implements additional checks
        /// specific to S3 on top of the checks in DefaultRetryPolicy.
        /// </summary>
        /// <param name="executionContext">Request context containing the state of the request.</param>
        /// <param name="exception">The exception thrown by the previous request.</param>
        /// <returns>Return true if the request should be retried.</returns>
        public override bool RetryForException(Runtime.IExecutionContext executionContext, Exception exception)
        {
            var syncResult = RetryForExceptionSync(executionContext, exception);

            if (syncResult.HasValue)
            {
                return(syncResult.Value);
            }
            else
            {
                var         serviceException = exception as AmazonServiceException;
                string      correctedRegion  = null;
                AmazonS3Uri s3BucketUri;
                if (AmazonS3Uri.TryParseAmazonS3Uri(executionContext.RequestContext.Request.Endpoint, out s3BucketUri))
                {
                    var credentials = executionContext.RequestContext.ImmutableCredentials;
                    if (credentials != null)
                    {
                        correctedRegion = BucketRegionDetector.DetectMismatchWithHeadBucketFallback(s3BucketUri, serviceException, credentials);
                    }
                }

                if (correctedRegion == null)
                {
                    return(base.RetryForException(executionContext, exception));
                }
                else
                {
                    // change authentication region of request and signal the handler to sign again with the new region
                    executionContext.RequestContext.Request.AuthenticationRegion = correctedRegion;
                    executionContext.RequestContext.IsSigned = false;
                    return(true);
                }
            }
        }
Beispiel #4
0
 /// <summary>
 /// Return true if the request should be retried. Implements additional checks
 /// specific to S3 on top of the checks in StandardRetryPolicy.
 /// </summary>
 /// <param name="executionContext">Request context containing the state of the request.</param>
 /// <param name="exception">The exception thrown by the previous request.</param>
 /// <returns>Return true if the request should be retried.</returns>
 public override async Task <bool> RetryForExceptionAsync(Runtime.IExecutionContext executionContext, Exception exception)
 {
     return(await AmazonS3RetryPolicy.SharedRetryForExceptionAsync(executionContext, exception, RetryForExceptionSync, base.RetryForException).ConfigureAwait(false));
 }
Beispiel #5
0
 /// <summary>
 /// Perform the processor-bound portion of the RetryForException logic.
 /// This is shared by the sync, async, and APM versions of the RetryForException method.
 /// </summary>
 /// <param name="executionContext"></param>
 /// <param name="exception"></param>
 /// <returns>a value if it can be determined, or null if the IO-bound calculations need to be done</returns>
 public bool?RetryForExceptionSync(Runtime.IExecutionContext executionContext, Exception exception)
 {
     return(SharedRetryForExceptionSync(executionContext, exception, Logger, base.RetryForException));
 }
 /// <summary>
 /// Return true if the request should be retried. Implements additional checks
 /// specific to S3 on top of the checks in StandardRetryPolicy.
 /// </summary>
 /// <param name="executionContext">Request context containing the state of the request.</param>
 /// <param name="exception">The exception thrown by the previous request.</param>
 /// <returns>Return true if the request should be retried.</returns>
 public override bool RetryForException(Runtime.IExecutionContext executionContext, Exception exception)
 {
     return(AmazonS3RetryPolicy.SharedRetryForException(executionContext, exception, RetryForExceptionSync, base.RetryForException));
 }