🔖

ActiveStorage::DiskController が返すファイルの Cache-Control ヘッダを設定する

2024/04/22に公開

ActiveStorage のディスクアダプタを利用している場合、応答として返すバイナリデータについて、キャッシュ制御したいとき、どのようにするか説明します。 Cache-Control; public を返すことで、ブラウザキャッシュや、CDNでのキャッシュを活用し、サーバとネットワークへの負荷の軽減に役立ちます。

動作確認したRailsのバージョン:7.1.3.2

オープンクラスを使って ActiveStorage::DiskControllerbefore_action を設定します。

config/initializers/active_storage.rb
Rails.application.reloader.to_prepare do
  class ActiveStorage::DiskController
    before_action only: [ :show ] do
      expires_in ActiveStorage.service_urls_expire_in, public: true
    end
  end
end

キャッシュ可能なURLを発行する

ActiveStorage::Variant#url (doc) expires_in: nil を渡すことで、URLの利用期限を削除します。 指定しない場合、URL生成時刻から デフォルト( ActiveStorage.service_urls_expire_in ) 分の間利用可能なURLであり、生成時刻でURLが変化するため、キャッシュできない。

app/views/posts/show.html.erb
<% if @post.image.attached? %>
  <%= image_tag @post.image.variant(:default).processed.url(expires_in: nil) %>
  <%= image_tag @post.image.representation(resize_to_limit: [100, 100]).processed.url(expires_in: nil) %>
<% end %>

独自のコントローラーで ActiveStorage::Variant#url などを使用する場合、ActiveStorage::SetCurrentinclude して、URLの組み立てに使用するホスト名などを設定します。

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  include ActiveStorage::SetCurrent # 

  def show
    @post = Post.find(params[:id])
  end
end
タケユー・ウェブ株式会社

Discussion