浏览器缓存 shrine s3 私有附件

browser caching shrine s3 private attachments

我刚刚在 s3 上创建了一个私有存储桶,用于包含用户个人资料图片。使用 public 桶,所有图像都被正确缓存(以前的回形针配置具有相同的设置)。

我有以下 shrine 初始化程序:

s3_options = {
  access_key_id: ENV['AWS_ACCESS_KEY_ID'],
  secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
  region: ENV['AWS_REGION'],
  bucket: ENV['S3_BUCKET_NAME']
}

Shrine.storages = {
  cache: Shrine::Storage::FileSystem.new('tmp', prefix: 'uploads/cache'),
  store: Shrine::Storage::S3.new(**s3_options)
}

Shrine.plugin :activerecord
Shrine.plugin :logging
Shrine.plugin :determine_mime_type
Shrine.plugin :cached_attachment_data
Shrine.plugin :restore_cached_data
Shrine.plugin :delete_promoted
Shrine.plugin :delete_raw
Shrine.plugin :remove_invalid

以及以下上传者:

class AvatarUploader < Shrine
  plugin :pretty_location
  plugin :processing
  plugin :upload_options, store: {
    acl: 'private',
    cache_control: "max-age=604800",
  }
end

CacheControl 在 s3 对象上正确设置为 1 周,并且在响应中可见。我注意到在每个请求上签名的 url 关于 X-Amz-Signature 散列的不同,这很可能导致缓存未命中(每个请求的 Etag 相同).我想这就是它不起作用的原因,但我不知道如何在对象未过期时使 X-Amz-Signature 相同。

ruby S3 SDK 会在您每次生成签名 URL 时生成一个新签名,这是设计使然。

你应该

a) 坚持 public,未签名的请求

b) 缓存已签名的url,这样就不会在每次调用时都生成一个新的签名,而是在签名过期之前过期

这样的事情可能会成功

def url
  Rails.cache.fetch("url", self, expires_in: 6.days) do
    super(public: false, expires_in: 1.week)
  end
end