Railsのreponseのcache-controlを上書きする

こんにちは!kossyです!



さて、今回はRailsAPIを実装する際に、responseのcache-controlを上書きする方法について
ブログに残してみたいと思います。

そもそもcache-controlってなに?

Cache-Control 一般ヘッダーフィールドは、リクエストとレスポンスの両方のキャッシュ規則を指定するために用います。キャッシュのディレクティブは単一方向であり、すなわちリクエストで指定されたディレクティブがレスポンスで同じディレクティブが指定されたものとはみなされません。

引用元: Cache-Control - HTTP | MDN

要はキャッシュをどう扱うかを指定するために用いるもののようです。

cache-controlディレクティブには、
・max-age
・no-cache
・no-store

上記のディレクティブを設定できます。
より詳しく知りたい方は引用元のページをご確認下さい。


実装手順

さて、cache-controlの非常に雑な紹介はここまでにして、
実装手順を残したいと思います。


app/controllers/application_controller.rb


class ApplicationController < ActionController::Base

  before_action :prevent_page_caching

  def prevent_page_caching
    response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
  end
end

参考: must-revalidate Cache-Control header disappearing in Rails 5.2 · Issue #32557 · rails/rails · GitHub

application_controller.rbにヘッダの中身を書き換えるprevent_page_cachingメソッドを定義し、before_actionコールバックで
ApplicationControllerを継承した全てのcontrollerでコールバックが実行されるようにしています。

no-cache, no-store, must-revalidateは、ざっくり言うと、

「有効かどうかの確認が取れないとキャッシュ使っちゃダメ」
「キャッシュしちゃダメ」
「キャッシュが有効かどうかの確認を絶対にしてね」

という設定になります。

参考: IPA ISEC セキュア・プログラミング講座:Webアプリケーション編 第5章 暴露対策:プロキシキャッシュ対策



このように設定すると、頻繁に画面のアップデートを行うようなWebアプリの場合だと、
手動でキャッシュを削除せずとも最新の変更が反映されるようになります。

ただ、キャッシュをしなくなるということは画面の描画に時間がかかるようになるので、
UX的な観点から言うと悪手かもしれません。

「手動でキャッシュを削除せずとも最新の変更が反映されるようにしたい」
という要件がもしあった場合、Railsのreponseのcache-controlを上書きする解決策を取ってもいいかもしれません。



参考にさせていただいた記事
must-revalidate Cache-Control header disappearing in Rails 5.2 · Issue #32557 · rails/rails · GitHub
IPA ISEC セキュア・プログラミング講座:Webアプリケーション編 第5章 暴露対策:プロキシキャッシュ対策