简体   繁体   English

使用AWS S3 REST API在不知道存储桶区域的情况下检索存储桶的对象

[英]Retrieve bucket's objects without knowing bucket's region with AWS S3 REST API

I'm trying to retrieve a bucket's objects with AWS S3 REST API (I'm not using the SDK) but unfortunately I'm facing the following problem : I don't know its region when I do the call to the API. 我正在尝试使用AWS S3 REST API检索存储桶的对象(我没有使用SDK),但不幸的是我遇到了以下问题:当我调用API时,我不知道它的区域。

Here's what I do : 这是我做的:

  • I build a request to "https:// [bucketname] .s3.amazonaws.com/" 我建立了一个“https:// [bucketname] .s3.amazonaws.com /”的请求
  • I sign the request using a default region set to "us-west-1" (using the AWS4 signature process) 我使用默认区域设置为“us-west-1”(使用AWS4签名过程)对请求进行签名
  • But imagine the bucket I'm trying to GET is set to the region "us-west-2", AWS is throwing me an error 但想象一下,我正试图获取的存储区设置为“us-west-2”区域,AWS正在向我发出错误

Therefore here's my question: 因此,这是我的问题:

Is there any way to get a list of the objects of a bucket without knowing its region ? 有没有办法在不知道其区域的情况下获取桶的对象列表? Or is there any simple way to get the region of a bucket ? 或者有没有简单的方法来获得桶的区域?

INFO : I've read there are two style to call a bucket, "path-style" and "virtual-hosted-style", but whenever I send the request to " https://s3.amazonaws.com/ [bucketname]" instead it gives me a redirectpermanent error... 信息:我读过有两种方式可以调用存储桶,“路径式”和“虚拟托管式”,但每当我将请求发送到“ https://s3.amazonaws.com/ [bucketname]时“相反,它给了我一个重定向的错误......

AWS V4 authentication requires that you know the bucket's region so that you can correctly sign the request. AWS V4身份验证要求您知道存储桶的区域,以便您可以正确签署请求。 Otherwise: 除此以外:

HTTP/1.1 400 Bad Request

<?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 'us-west-2'</Message>
  <Region>us-west-2</Region>
  <RequestId>xxxx</RequestId>
  <HostId>xxxx</HostId>
</Error>

V2 signatures were not region-specific, so there was previously a simple way you could learn the bucket's region using a V2 request: V2签名不是特定于区域的,因此以前有一种简单的方法可以使用V2请求来学习桶的区域:

http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETlocation.html http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETlocation.html

However, there apprears to be a catch-22 with V4, since you have to know the bucket's region before you can make the call to discover the bucket's region. 但是,有一个可以成为V4的catch-22,因为你必须知道桶的区域才能调用以发现桶的区域。

The first solution, then, is to capture the <Region> returned in the error response and use that region for signing future requests for the bucket. 然后,第一个解决方案是捕获错误响应中返回的<Region> ,并使用该区域来标记存储桶的未来请求。 Obviously, you'd want to cache this information, since not doing so would lower performance and increase costs. 显然,您希望缓存此信息,因为不这样做会降低性能并增加成本。

Alternately, there is a way to ask the US-Standard region (us-east-1) about the location of any bucket, in any region, using this URL format only : 或者,有一种方法可以向美国标准区域(us-east-1)询问任何区域中任何桶的位置, 使用此URL格式:

https://s3.amazonaws.com/bucket-name?location

Sign this request with the us-east-1 region and you will get a response, wherever the bucket happens to be. 使用us-east-1区域对此请求进行签名,无论桶在哪里,您都会得到响应。 Note that if the bucket is in us-east-1 (US-Standard) the LocationConstraint is returned empty. 请注意,如果存储桶位于us-east-1(美国标准版)中,则LocationConstraint将返回为空。

<?xml version="1.0" encoding="UTF-8"?>
<LocationConstraint xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  us-west-2
</LocationConstraint>

You cannot use this URL construct for actually listing bucket objects in other regions, since https://s3.amazonaws.com/ always routes your request to US-Standard (us-east-1) but you can use it to discover the region of any bucket, since US-Standard has that information available. 您不能使用此URL构造实际列出其他区域中的存储桶对象,因为https://s3.amazonaws.com/始终将您的请求路由到US-Standard(us-east-1),但您可以使用它来发现该区域任何桶,因为美国标准有这方面的信息。


Update/Additonal 更新/产生额外的

At some point, S3 appears to have added a new response header, x-amx-bucket-region: which appears to be an undocumented addition to the REST API, and appears to be added to many S3 error responses, particularly 403 errors. 在某些时候,S3似乎添加了一个新的响应头x-amx-bucket-region:似乎是对REST API的一个未记录的添加,并且似乎被添加到许多S3错误响应中,特别是403错误。

This seems like a useful mechanism for self-correction if you receive an error response. 如果您收到错误响应,这似乎是一种有用的自我纠正机制。

Also, the information above about interrogating the US-Standard region about the location of any bucket anywhere is still accurate, and the same request should work if sent to any regional S3 REST endpoint, not just US-Standard, since all regions are aware of the location of all other buckets: eg https://s3-us-west-2.amazonaws.com/bucket-name?location would ask US-West-2 (Oregon), which also has the same information available, for any bucket globally. 此外,上述有关询问美国标准区域任何桶位置的信息仍然准确,如果发送到任何区域S3 REST端点,而不仅仅是美国标准,则相同的请求应该有效,因为所有地区都知道所有其他水桶的位置:例如https://s3-us-west-2.amazonaws.com/bucket-name?location会询问US-West-2(俄勒冈州),它们也提供相同的信息。桶全球。 It might be desirable in some cases to interrogate your nearest region. 在某些情况下,可能需要询问最近的区域。

You could get the region from the exception -> additional details 您可以从异常中获取该区域 - >其他详细信息

            AmazonS3 client = AmazonS3ClientBuilder.standard()
            .withCredentials(new AWSStaticCredentialsProvider(credentials)).withRegion(Regions.US_EAST_1).build();
            Regions bucketRegion = Regions.US_EAST_1;    
            try {
                client.getBucketLocation(bucket.getName());
            } catch (AmazonS3Exception e) {
                bucketRegion = Regions.fromName(e.getAdditionalDetails().get("Region"));
            }

Its not the best way of doing it but right now there is no alternative to do it. 它不是最好的方式,但现在没有其他选择。

If your request is simply pointing to the wrong region, S3 will respond with a temporary redirect. 如果您的请求只是指向错误的区域,S3将使用临时重定向进行响应。 Since you mentioned it's replying with a permanent redirect, that indicates the request is incorrect. 由于您提到它使用永久重定向进行回复,因此表明请求不正确。 S3 usually replies with a helpful message inside the response body to help figure out the issue. S3通常会在响应正文中回复一条有用的消息,以帮助找出问题所在。 You'd want to read the body of the response to correct the request. 您需要阅读响应正文以更正请求。

在Ruby中,您可以在获取资源时传递区域:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM