Shrine

Allow `presigner` for Storage

Like the signer option on Shrine::Storage::S3, it would be nice to have a presigner option to gain more central control over the generation of a presigned upload URL.

My scenario is lie this:
For local development, I use minio in a docker compose environment.
Which poses the difficulty, that for my Rails app the S3 endpoint is “minio:9000” (the docker compose service name),
but for my browser it’s “localhost:9000” (forwarded port from docker compose).

For generating signed download URLs I’m using the signer option on Storage::S3 to use a proc which uses a Aws::S3::Client configures with the “public” endpoint (“localhost:9000”).

For generating presigned upload URLs, there’s no such option. The presign_endpoint plugin allows to customize the presign, but thats on a Uploader level. Also, by default, it delegates to S3#presign

I’ve wrapped S3 like this, and adopted how url uses signer and it seems to work just fine. Just, that it does URL generation twice, once in super and once with the given presigner if given.

class Shrine::Storage::PresignS3 < Shrine::Storage::S3
  attr_reader :presigner

  def initialize(presigner: nil, **options)
    super(**options)
    @presigner = presigner
  end

  def presign_post(id, options)
    h = super
    if presigner
      url = object(id).public_url(**options)
      h[:url] = presigner.call(:post_object, url, options)
    end
    h
  end

  def presign_put(id, options)
    h = super
    if presigner
      url = object(id).public_url(**options)
      h[:url] = presigner.call(:put_object, url, options)
    end
    h
  end
end

So, I was wondering, if we could get this (or something like this) directly in Shrine.