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

时间:2014-11-23 17:14:19

标签: rest amazon-web-services amazon-s3

我尝试使用AWS S3 REST API检索存储桶的对象(我没有使用SDK)但不幸的是我遇到了以下问题:我没有&#39 ;当我调用API时,我知道它的区域。

这就是我的所作所为:

  • 我建立了一个请求" https:// [bucketname] .s3.amazonaws.com /"
  • 我使用默认区域设置为" us-west-1" (使用AWS4签名过程)
  • 但是想象一下,我试图获取GET的存储区域设置为" us-west-2&#34 ;, AWS正在向我发送错误

因此,我的问题是:

有没有办法在不知道其区域的情况下获取桶的对象列表?或者有没有简单的方法来获取桶的区域?

信息:我读过有两种叫斗的风格,"路径风格"和"虚拟托管式",但每当我将请求发送到" https://s3.amazonaws.com/ [bucketname]"相反,它给了我一个重定向永久错误...

5 个答案:

答案 0 :(得分:11)

AWS V4身份验证要求您知道存储区的区域,以便您可以正确签署请求。否则:

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签名不是特定于区域的,所以以前有一种简单的方法可以使用V2请求来学习桶的区域:

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

但是,有一个关于V4的捕获22,因为你必须知道桶的区域才能调用以发现桶的区域。

然后,第一个解决方案是捕获错误响应中返回的<Region>,并使用该区域来标记存储桶的未来请求。显然,您希望缓存此信息,因为不这样做会降低性能并增加成本。

或者,有一种方法可以使用此URL格式 向美国标准区域(us-east-1)询问任何区域中任何存储桶的位置:

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

使用us-east-1区域签署此请求,无论桶在哪里,您都会得到响应。请注意,如果存储桶位于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>

您不能使用此URL构造实际列出其他区域中的存储桶对象,因为https://s3.amazonaws.com/始终将您的请求路由到US-Standard(us-east-1),但您可以使用它来发现任何区域因为美国标准有这方面的信息。


<强>更新/产生额外

在某些时候,S3似乎添加了一个新的响应标头,x-amx-bucket-region: 出现,作为REST API的未记录添加,出现要添加到许多S3错误响应中,特别是403错误。

如果收到错误回复,这似乎是一种有用的自我纠正机制。

此外,上述有关询问美国标准区域任何桶位置的信息仍然准确,如果发送到任何区域S3 REST端点,而不仅仅是美国标准,则相同的请求应该有效,因为所有地区知道所有其他桶的位置:例如https://s3-us-west-2.amazonaws.com/bucket-name?location会询问US-West-2(俄勒冈州),它也有相同的信息,可用于全球任何一个桶。在某些情况下,可能需要询问最近的地区。

答案 1 :(得分:1)

您可以从例外中获取该区域 - &gt;其他细节

            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"));
            }

这不是最好的方法,但现在没有别的选择。

答案 2 :(得分:0)

如果您的请求只是指向错误的区域,则S3会以临时重定向进行响应。由于您提到它使用永久重定向进行回复,因此表明请求不正确。 S3通常会在响应正文中回复一条有用的消息,以帮助找出问题所在。您需要阅读响应正文以更正请求。

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

在@ patrice-gagnon响应之后,我将区域配置注入到AWS实例中,并且对我有用。

通过我在NestJS中使用Typescript的方式

const s3 = new AWS.S3({ region: 'eu-west-3' });
相关问题