当前位置: 首页 > 知识库问答 >
问题:

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

麹学文
2023-03-14

我试图用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个答案

吴峰
2023-03-14

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(俄勒冈),它也有同样的信息,可以在全球范围内查询任何桶。在某些情况下,询问你最近的地区可能是可取的。

 类似资料:
  • 我正在使用一个PHP库将一个文件上传到我的bucket中。我已经将ACL设置为public read write,它可以正常工作,但文件仍然是私有的。 我发现如果我把被授权人改成所有人,文件就会公开。我想知道的是,如何将bucket中所有对象的默认grante设置为“Everyone”。或者有没有另一种默认公开文件的解决方案? 我使用的代码如下:

  • 我知道协议缓冲区是一种序列化格式,需要中的消息格式。proto,以便正确读回。但我有一个文件,我不知道正确的消息格式,因为它没有发布。我想做的是自己对数据进行反向工程,这样我就可以重建消息。为此,我需要读取原始文件,从中可以提取字段编号、类型和值。 有没有一个程序可以做到这一点(最好是在python中,但C/C也很酷)?

  • 问题内容: 这是我的json: 有什么方法可以在不知道键是什么的情况下访问此数组中的键和值(在javascript中)? 我的json这样构造的原因是,我通过jquery调用的网络方法正在返回字典。如果无法使用上述方法,那么我需要对返回数据的方式进行哪些更改? 这是我的网络方法的概述: 问题答案: 您可以使用该构造遍历对象的任意属性:

  • 我在处理多维数组时遇到问题。我试图使用指针让“123”、“456”、“x123”和“x456”出现在函数内部的屏幕上: 编译时,我在

  • 我正在实现一个排序列表类,在这个类中,我将对任何类型的对象进行排序,所以现在我想测试对象是否具有可比性, 我用这段代码覆盖了compareTo()方法:- 所以现在我需要给这些对象分配数字,像这样 但它总是给我一个例外:- 线程“main”中出现异常Java . lang . classcastexception:Java . lang . integer不能转换为java.lang.String

  • 我的主要目的是在用户点击按钮时打开安装在客户端(用户手机)上的日历应用程序。 问题是有这么多不同的Android设备,每个都有不同的股票日历应用程序包名。第二个问题是,如果用户有第三方日历应用程序,比如Jorte,该怎么办。 所以我想到的是使用Intent来过滤特定应用程序的解决方案,在这种情况下是日历应用程序。所以用户可以选择要选择的日历应用程序。我在这里看到了一个例子,但是它需要我们知道包的名