Skip to content

Commit

Permalink
Fix for Aws::S3::Bucket#exists?
Browse files Browse the repository at this point in the history
Fixed the following issue:

  s3 = Aws::S3::Resource.new(region: 'us-west-1')

  s3.bucket('us-west-2-bucket-you-dont-own').exists?
  #=> raises Aws::S3::Errors::BadRequest

If the bucket exists, but you are configured for the incorrect region,
the SDK fails to extract the actual bucket region from the 400 response.
This is due to the fact that HEAD reponses do not have a body.

Added a check for the "x-amz-bucket-region" header before checking the
body. This the SDK to determine the proper signing region for the
request.

This change currently lacks tests.

See #1161
  • Loading branch information
trevorrowe committed Apr 18, 2016
1 parent 0960da2 commit c3a61b6
Showing 1 changed file with 12 additions and 6 deletions.
18 changes: 12 additions & 6 deletions aws-sdk-core/lib/aws-sdk-core/plugins/s3_request_signer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,8 @@ def handle_region_errors(response)
end

def get_region_and_retry(context)
actual_region = region_from_body(context)
if actual_region.nil? || actual_region == ""
raise "Couldn't get region from body: #{context.body}"
end
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)
update_region_header(context, actual_region)
Expand All @@ -116,7 +114,10 @@ def update_bucket_cache(context, actual_region)

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

def update_region_header(context, region)
Expand All @@ -128,8 +129,13 @@ def update_region_header(context, region)
signer.sign(context.http_request)
end

def region_from_body(context)
context.http_response.body_contents.match(/<Region>(.+?)<\/Region>/)[1]
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

def log_warning(context, actual_region)
Expand Down

0 comments on commit c3a61b6

Please sign in to comment.