Search code examples
ruby-on-railsamazon-web-servicesamazon-s3rails-activestorage

How can I access URL of an ActiveStorage attachment at S3?


I migrated form paperclip to ActiveStorage and I'm struggling a litte with URLs. I was using service_url, but wasn't working for me because everytime you call that function, it returns a different URL.

Im trying to use Rails.application.routes.url_helpers.rails_blob_path. Locally, it works. I just have to acess http://localhost:3000/rails/active_storage/disk/<etc>, where rails/active_storage/disk/<etc> was given to me from the method call.

But how can I access this from my Amazon S3? I enabled static website hosting, but if I hit http://my-production-bucket.s3-website.sa-east-1.amazonaws.com/rails/active_storage/blobs/<etc>, I get an error. Im I hitting the wrong endpoint/wrong host? What else should I do to get an unique (not dynamic) URL, is there another easiest way?

My storage.yml:

amazon:
  service: S3
  access_key_id: <%= ENV['AWS_KEY'] %>
  secret_access_key: <%= ENV['AWS_SECRET'] %>
  region: 'sa-east-1'
  bucket: 'production-bucket'

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

production.rb:

config.active_storage.service = :amazon

Solution

  • Check the docs for service_url https://api.rubyonrails.org/v5.2.0/classes/ActiveStorage/Variant.html#method-i-service_url

    Returns the URL of the variant on the service. This URL is intended to be short-lived for security and not used directly with users. Instead, the service_url should only be exposed as a redirect from a stable, possibly authenticated URL. Hiding the service_url behind a redirect also gives you the power to change services without updating all URLs. And it allows permanent URLs that redirect to the service_url to be cached in the view.

    Use url_for(variant) (or the implied form, like +link_to variant+ or +redirect_to variant+) to get the stable URL for a variant that points to the ActiveStorage::VariantsController, which in turn will use this service_call method for its redirection.

    It recommends you to implement some kind of proxy action on your app. You give the fixed url for that action and then redirect the request to the current service_url.