Rails now serves files via proxy


Rails has always been known for having everything available right out of the box. However, one place that it struggles with is storage. With the introduction of Rails 5 and 6, there have been many improvements to ActiveStorage over the years. Instead of using a myriad of gems to get basic functionalities up and running, we can now just depend on Rails core. One such feature has been the ability to serve files via proxying.

Before we dive deep, let’s understand what it means to proxy and what a proxy server is. Proxy in the English sense means to give authority to someone to act on your behalf. Porting that over to the Computer Science side of things, a proxy server essentially acts as a bypass to the originating request. The request is not fulfilled by the intended server, but rather the request is offloaded to a proxy server which then responds.

This is especially useful when serving static assets like file uploads. Our Rails server should only be responsible for responding to business logic queries, other resource-heavy tasks like file serving can be offloaded to CDNs. These CDNs offer an array of improvements when serving files like the ability to stream, have multiple serving locations and more.

Before

Before the introduction of proxying, files were served directly by the webserver. This reduces pressure on our app server, but there was still scope for improvement. ActiveStorage generates URLs for files that, when accessed, redirect to signed, short-lived service URLs. It is the default file serving strategy.

  <%= image_tag rails_storage_redirect_path(current_user.profile_picture) %>

After

With the introduction of proxying, files can now be served by the underlying storage service instead of redirecting to a signed service URL.

To enable this, set config.active_storage.resolve_model_to_route:

  config.active_storage.resolve_model_to_route = :rails_storage_proxy

And now we can simply do,

  <%= image_tag current_user.profile_picture %>

If we want to explicitly proxy specific attachments, we can still use the below code:

  <%= image_tag rails_storage_proxy_path(current_user.profile_picture) %>