How to use GET Bucket location on Amazon S3 with Racket
In Racket I want to iterate over my buckets in Amazon S3. They are located in different regions. So how do I get my bucket’s location/region? In the API Reference there is a call GET Bucket location. I use Greg’s AWS library for Racket and this library authenticates its calls with signature version V4. But V4 requires the user to know the region to correctly sign the request. So I need to know the region to ask Amazon S3 for the region where the bucket is located. Otherwise Amazon S3 responds with an error:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>AuthorizationHeaderMalformed</Code>
<Message>The authorization header is malformed; the region 'us-east-1'
is wrong; expecting 'eu-central-1'</Message>
<Region>eu-central-1</Region>
<RequestId>XXXX</RequestId>
<HostId>XXXX>
</Error>
After some search on the net I found a post on Stackoverflow that helped to solve that issue: If I use the URL format (instead of the normally used virtual host format) I could get the location of any bucket. Every region responds with a LocationConstraint answer.
Therefore a code snippet for Racket could be:
(define (get-bucket-location bucket)
(parameterize
([s3-path-requests? #t])
(define xpr (get/proc (string-append bucket "/?location") read-entity/xexpr))
(and (list? xpr)
(= (length xpr) 3)
(third xpr))))
For example:
> (get-bucket-location "my-bucket-somewhere")
"eu-central-1"
PS: I think official Amazon S3 documentation could be a bit more verbose on the issues with GetBucketLocation and signature V4.
Update: Greg added a bucket-location
function to his great library