public bool? RetryForExceptionSync(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;
}
else
{
// this means that the synchronous check is inconclusive and
// the caller needs to check for a bucket/region mismatch
return null;
}
}
}
return base.RetryForException(executionContext, exception);
}
}