提问者:小点点

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


我试图用AWS3REST API检索桶的对象(我没有使用SDK),但不幸的是,我面临以下问题:当我调用API时,我不知道它的区域。

我是这么做的:

  • 我生成了一个对“https://[bucketname].s3.amazonaws.com/”
  • 的请求
  • 我使用设置为“US-West-1”的默认区域对请求进行签名(使用AWS4签名过程)
  • 但假设我尝试获取的bucket设置为“US-West-2”区域,AWS会给我一个错误

所以我的问题是:

有什么方法可以在不知道桶的区域的情况下获得桶的对象列表吗?或者有什么简单的方法可以得到一个桶的区域吗?

信息:我读过有两种调用bucket的样式,“路径样式”和“虚拟主机样式”,但当我将请求发送到“https://s3.amazonaws.com/[bucketname]”时,它会给我一个redirectpermanent错误...


共1个答案

匿名用户

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请求了解bucket的区域:

http://docs.aws.amazon.com/amazons3/latest/api/restbucketgetlocation.html

然而,在V4中可能会遇到一个难题,因为在调用发现桶的区域之前,您必须知道桶的区域。

第一种解决方案是捕获错误响应中返回的,并使用该区域对bucket的未来请求进行签名。显然,您希望缓存这些信息,因为不这样做会降低性能并增加成本。

或者,也可以仅使用以下URL格式向美国标准区域(us-east-1)询问任何区域中任何桶的位置:

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

在us-east-1区域签署此请求,您将得到响应,无论桶碰巧在哪里。注意,如果bucket是us-east-1(US-Standard),则LocationConstraint返回为空。

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

您不能使用此URL构造来实际列出其他区域中的bucket对象,因为https://s3.amazonaws.com/总是将您的请求路由到US-Standard(us-east-1),但是您可以使用它来发现任何bucket的区域,因为US-Standard提供了这些信息。

更新/增补

在某个时刻,S3似乎添加了一个新的响应头x-amx-bucket-region:,这似乎是REST API中未记录的添加,并且似乎添加到了许多S3错误响应中,特别是403错误。

如果您收到错误响应,这似乎是一种有用的自我更正机制。

此外,上面关于询问美国标准地区关于任何地方的桶的位置的信息仍然是准确的,并且如果将相同的请求发送到任何地区的S3 REST端点,而不仅仅是美国标准的,那么同样的请求也会起作用,因为所有地区都知道所有其他桶的位置:例如,https://s3-us-west-2.amazonaws.com/bucket-name?location会询问US-West-2(俄勒冈),它也有同样的信息,可以在全球范围内查询任何桶。在某些情况下,询问你最近的地区可能是可取的。