Ali Ilman
Ali Ilman

Reputation: 180

ActiveStorage's rails_blob_url returning a link that shows a page with 404 error when opened

I have an attachment, that is passed to the frontend through a serializer as follows.

module NameOfSerializer
  class Base < ActiveModel::Serializer
    attributes :id,
               ...
               ...
               ...
               :attachment_url

    def attachment_url
      Rails.application
           .routes.url_helpers
           .rails_blob_url(object.attachment, host: ENV['HOST_URL'])
    end
  end
end

On development and staging, it works perfectly. I can copy paste the URL and one can open and view the attachment. But on production, it's showing a page with 404 error.

This is what I found in the AWS Elastic Beanstalk log.

[2019-02-04T03:50:38.733073 #16644]  INFO -- : [4ca0d491-66cc-4594-9db4-75da533d2fbc] Started GET "/rails/active_storage/blobs/insert_signed_id_here/20190131_214818%20copy%202.jpg" at 2019-02-04 03:50:38 +0000
I, [2019-02-04T03:50:38.736005 #16644]  INFO -- : [4ca0d491-66cc-4594-9db4-75da533d2fbc] Processing by ActiveStorage::BlobsController#show as JPEG
I, [2019-02-04T03:50:38.736056 #16644]  INFO -- : [4ca0d491-66cc-4594-9db4-75da533d2fbc]   Parameters: {"signed_id"=>"insert the signed_id here", "filename"=>"20190131_214818 copy 2"}
D, [2019-02-04T03:50:38.737552 #16644] DEBUG -- : [4ca0d491-66cc-4594-9db4-75da533d2fbc]   [1m[36mActiveStorage::Blob Load (0.9ms)[0m  [1m[34mSELECT  "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = $1 LIMIT $2[0m  [["id", 16], ["LIMIT", 1]]
I, [2019-02-04T03:50:38.737936 #16644]  INFO -- : [4ca0d491-66cc-4594-9db4-75da533d2fbc] Completed 404 Not Found in 2ms (ActiveRecord: 0.9ms)
F, [2019-02-04T03:50:38.740120 #16644] FATAL -- : [4ca0d491-66cc-4594-9db4-75da533d2fbc]   
F, [2019-02-04T03:50:38.740163 #16644] FATAL -- : [4ca0d491-66cc-4594-9db4-75da533d2fbc] ActiveRecord::RecordNotFound (Couldn't find ActiveStorage::Blob with 'id'=16):
F, [2019-02-04T03:50:38.740185 #16644] FATAL -- : [4ca0d491-66cc-4594-9db4-75da533d2fbc]   
F, [2019-02-04T03:50:38.740215 #16644] FATAL -- : [4ca0d491-66cc-4594-9db4-75da533d2fbc] activerecord (5.2.0) lib/active_record/core.rb:177:in `find'

I was surprised to see that the log says the Blob with id 16 isn't found, but when I ran rails c on Elastic Beanstalk, I found the blob. I also tested another way of retrieving the file from S3 in rails console by running attachment.service_url. I was able to access the attachment. Didn't run into 404 errors.

Any ideas? I encountered this issue before and for that issue, I changed to using service_url but I'd like to know what's causing rails_blob_url to not work on production environment.

Upvotes: 3

Views: 3395

Answers (1)

soundly_typed
soundly_typed

Reputation: 40386

I just ran into this. Here's how I fixed it for my project.

First, I'm using Amazon S3 for production, but also development. That second part is crucial.

In other words, my config/environments/development.rb had this:

# Store uploaded files on the local file system (see config/storage.yml for options).
# config.active_storage.service = :local
config.active_storage.service = :amazon

However, this by itself is not enough. For some reason, Rails still tries to use local when generating urls.

The workaround is to remove the local config. Here's what my storage.yml looks like afterwards:

# THE FIX: COMMENTED THIS OUT
# local:
#   service: Disk
#   root: <%= Rails.root.join("storage") %>

# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: us-east-2
  bucket: xxx

After restarting the server, everything worked pleasantly.

Upvotes: 3

Related Questions