1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
require 'cgi'
module AWS
class S3
# @api private
module RegionDetection
private
def retry_server_errors(&block)
response = super
if requires_sigv4?(response)
detect_region_and_retry(response, &block)
else
response
end
end
def requires_sigv4?(resp)
resp.http_response.status == 400 &&
resp.http_response.body &&
resp.http_response.body.include?('Please use AWS4-HMAC-SHA256')
end
def detect_region_and_retry(response, &retry_block)
updgrade_to_v4(response, 'us-east-1')
yield
return if response.http_response.status == 200
actual_region = region_from_location_header(response)
updgrade_to_v4(response, actual_region)
log_region_warning(response, actual_region)
yield
end
def updgrade_to_v4(response, region)
bucket = response.request_options[:bucket_name]
if response.http_request.body_stream.respond_to?(:rewind)
response.http_request.body_stream.rewind
end
response.http_request.headers.delete('authorization')
response.http_request.headers.delete('x-amz-security-token')
response.http_request.host = new_hostname(response, region)
new_v4_signer(region).sign_request(response.http_request)
end
def region_from_location_header(response)
location = response.http_response.headers['location'].first
location.match(/s3\.(.+?)\.amazonaws\.com/)[1]
end
def new_v4_signer(region)
Core::Signers::Version4.new(credential_provider, 's3', region)
end
def new_hostname(response, region)
bucket = response.request_options[:bucket_name]
if region == 'us-east-1'
's3-external-1.amazonaws.com'
else
"s3.#{region}.amazonaws.com"
end
end
def log_region_warning(response, actual_region)
bucket_name = response.request_options[:bucket_name]
S3::BUCKET_REGIONS[bucket_name] = actual_region
log_warning("S3 client configured for #{@region.inspect} " +
"but the bucket #{bucket_name.inspect} is in" +
"#{actual_region.inspect}; Please configure the proper region " +
"to avoid multiple unecessary redirects and signing attempts\n")
end
end
end
end
|