class Aws::S3::Plugins::S3Signer::BucketRegionErrorHandler
This handler detects when a request fails because of a mismatched bucket region. It follows up by making a request to determine the correct region, then finally a version 4 signed request against the correct regional endpoint.
Public Instance Methods
call(context)
click to toggle source
# File lib/aws-sdk-s3/plugins/s3_signer.rb, line 129 def call(context) response = @handler.call(context) handle_region_errors(response) end
Private Instance Methods
custom_endpoint?(resp)
click to toggle source
# File lib/aws-sdk-s3/plugins/s3_signer.rb, line 163 def custom_endpoint?(resp) resolved_suffix = Aws::Partitions::EndpointProvider.dns_suffix_for( resp.context.config.region ) !resp.context.http_request.endpoint.hostname.include?(resolved_suffix) end
fips_region?(resp)
click to toggle source
# File lib/aws-sdk-s3/plugins/s3_signer.rb, line 159 def fips_region?(resp) resp.context.http_request.endpoint.host.include?('fips') end
get_region_and_retry(context)
click to toggle source
# File lib/aws-sdk-s3/plugins/s3_signer.rb, line 146 def get_region_and_retry(context) actual_region = context.http_response.headers['x-amz-bucket-region'] actual_region ||= region_from_body(context.http_response.body_contents) update_bucket_cache(context, actual_region) log_warning(context, actual_region) resign_with_new_region(context, actual_region) @handler.call(context) end
handle_region_errors(response)
click to toggle source
# File lib/aws-sdk-s3/plugins/s3_signer.rb, line 136 def handle_region_errors(response) if wrong_sigv4_region?(response) && !fips_region?(response) && !custom_endpoint?(response) get_region_and_retry(response.context) else response end end
log_warning(context, actual_region)
click to toggle source
# File lib/aws-sdk-s3/plugins/s3_signer.rb, line 205 def log_warning(context, actual_region) msg = "S3 client configured for #{context.config.region.inspect} " \ "but the bucket #{context.params[:bucket].inspect} is in " \ "#{actual_region.inspect}; Please configure the proper region " \ "to avoid multiple unnecessary redirects and signing attempts\n" if (logger = context.config.logger) logger.warn(msg) else warn(msg) end end
region_from_body(body)
click to toggle source
# File lib/aws-sdk-s3/plugins/s3_signer.rb, line 196 def region_from_body(body) region = body.match(/<Region>(.+?)<\/Region>/)[1] if region.nil? || region == '' raise "couldn't get region from body: #{body}" else region end end
resign_with_new_region(context, actual_region)
click to toggle source
# File lib/aws-sdk-s3/plugins/s3_signer.rb, line 176 def resign_with_new_region(context, actual_region) context.http_response.body.truncate(0) context.http_request.endpoint.host = S3Signer.new_hostname( context, actual_region ) context.metadata[:redirect_region] = actual_region # if it's an ARN, use the service in the ARN if (arn = context.metadata[:s3_arn]) service = arn[:arn].service end Aws::Plugins::SignatureV4.apply_signature( context: context, signer: S3Signer.build_v4_signer( service: service || 's3', region: actual_region, credentials: context.config.credentials ) ) end
update_bucket_cache(context, actual_region)
click to toggle source
# File lib/aws-sdk-s3/plugins/s3_signer.rb, line 155 def update_bucket_cache(context, actual_region) S3::BUCKET_REGIONS[context.params[:bucket]] = actual_region end
wrong_sigv4_region?(resp)
click to toggle source
# File lib/aws-sdk-s3/plugins/s3_signer.rb, line 170 def wrong_sigv4_region?(resp) resp.context.http_response.status_code == 400 && (resp.context.http_response.headers['x-amz-bucket-region'] || resp.context.http_response.body_contents.match(/<Region>.+?<\/Region>/)) end