AWS Ruby 绑定与 S3 的 AWS CLI 不一致?

AWS Ruby bindings not at parity with AWS CLI for S3?

我想设置能够对存储在 S3 存储桶中的 50 多个文件设置元数据,但 AWS CLI 不直接支持简单地更改元数据。元数据的目的是在 Web 浏览器请求这些文件时发出 HTTP 301 重定向。每个桶只允许 50 条规则,因此必须应用 per-object 元数据,而不是在 XML 或 JSON.

中编写规则

AWS CLI 仅支持在复制过程中设置元数据; AWS CLI 和 SDK 的这一缺陷令人遗憾,但作为所有语言绑定基础的 REST 接口显然不提供该功能。我见过几种执行复制的方法,包括(重新)复制一个文件并在复制过程中设置元数据。

这是一种方法,它(重新)复制 old_file.html 到 S3 存储桶并设置所需的元数据(导致 HTTP 301 重定向的 header):

$ aws s3 cp \
  old_file.html \
  s3://bucket_name/old_file.html \
  --website-redirect /new_file.html

笨拙,但可行。如果使用 CloudFront,则在 301 重定向实际发送到 Web 浏览器之前需要缓存失效:

$ aws cloudfront create-invalidation \
  --distribution-id "$AWS_CLOUDFRONT_DIST_ID" \
  --paths "old_file.html"

没问题。对失效的发生稍有耐心,重定向最终会起作用。

使用 Ruby v3 binding 时事情似乎变得更难了。上面的尴尬似乎没有直接的类比。

等效 Ruby 代码的建议?我当然可以 shell 从 Ruby 退出并调用 AWS CLI(如果必须的话,我会这样做),但这感觉就像作弊。

AWS 文档有时会以比必要的更复杂的方式解释事情。这就是将本地文件 (old_path) 上传到 bucket 并将对该文件的请求重定向到之前上传的另一个文件 (new_path) 所需的全部内容。

def redirect(bucket, old_path, new_path)
  s3 = Aws::S3::Client.new
  s3.put_object({
    body: IO.read(old_path),
    bucket: bucket,
    key: old_path,
    website_redirect_location: new_path,
  })
end

代码假定 ~/.aws/config 存在。否则,Aws::S3::Client.new 将引发异常。

我在这里详细写过:HTTP 301 Redirects with Jekyll and AWS S3