HTTP の Cache-Control ヘッダについて

2021年2月21日 engineering

こんにちは、 @kz_morita です。

最近, Web配信の技術 - HTTPキャッシュ・リバースプロキシ・CDNを活用する の本を読んでいて,Cache-Control 難しいなと思ったのでメモがてらまとめます.

Web配信の技術 - HTTPキャッシュ・リバースプロキシ・CDNを活用する

Cache-Control ヘッダー

HTTP でキャッシュに関係する設定を行うヘッダーです.リクエスト時とレスポンス時の両方に指定できるようです.

リクエスト時
Cache-Control: max-age=<seconds>
Cache-Control: max-stale[=<seconds>]
Cache-Control: min-fresh=<seconds>
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: no-transform
Cache-Control: only-if-cached
レスポンス時
Cache-Control: must-revalidate
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: no-transform
Cache-Control: public
Cache-Control: private
Cache-Control: proxy-revalidate
Cache-Control: max-age=<seconds>
Cache-Control: s-maxage=<seconds>

また,対応していないブラウザもありますが,以下の拡張もあります.

Cache-Control: immutable
Cache-Control: stale-while-revalidate=<seconds>
Cache-Control: stale-if-error=<seconds>

キャッシュの種類

キャッシュの性質による種別について書いていきます.

キャッシュには,privateshared があります.

private キャッシュは,クライアント(ブラウザ) にのみキャッシュできるものです.shared キャッシュは,クライアントの他にネットワーク上の経路でもキャッシュできるものになります.

これは privateキャッシュは,ユーザー単位のキャッシュであるのに対し,複数ユーザー間で共有できるのが shared キャッシュです.ユーザーの秘匿情報をキャッシュしてしまってセキュリティ事故になってしまったというようなケースは,意図せず shared キャッシュにしてしまったという原因が考えられます.

以下のように,private を指定すると,shared キャッシュを許可しない設定になります.

Cache-Control: private

キャッシュしない設定

ここでは,キャッシュをしないための設定をまとめます.

MDNによると以下のように,no-store を設定することが推奨されています.

Cache-Control: no-store
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Cache-Control#preventing_caching

また,冒頭で紹介した書籍には以下のような設定がおすすめされています.

Cache-Control: private, no-store, no-cache, must-revalidate

しかし,MDNでは 悪い例 として以下が紹介されていました.(書籍の記述と近い…)

Cache-Control: private,no-cache,no-store,max-age=0,must-revalidate,pre-check=0,post-check=0

こちらどのような指定が適切かは要検証なのかなと思います.

一応ここに登場した,ディレクティブの説明をします.

Cache-Control: private

先程も軽く触れましたが,shared キャッシュとして,経路上にキャッシュすることを設定しないディレクティブです.

https://triple-underscore.github.io/RFC7234-ja.html#section-5.2.2.6

Cache-Control: no-store

キャッシュを格納しない設定です. private, shared 両方に適用されます.

https://triple-underscore.github.io/RFC7234-ja.html#cache-request-directive.no-store

Cache-Control: no-cache

オリジンサーバーでの確認なしに,キャッシュを利用しては行けないという指定です.

https://triple-underscore.github.io/RFC7234-ja.html#cache-request-directive.no-cache

Cache-Control: must-revalidate

キャッシュの有効期限が切れた際にオリジンサーバーに再検証しに行きますが,その際にオリジンサーバーがダウンなどをした場合に,通常では期限切れのキャッシュでも再利用するという動作をすることがあります.

must-revalidate を指定すると,必ずオリジンサーバーに問い合わせるようになり,ダウンしたときは 504 Gateway Timeout を返すようになり意図せずキャッシュが使われることを防ぎます.

https://triple-underscore.github.io/RFC7234-ja.html#cache-response-directive.must-revalidate

まとめ

今回は,Cache-Control について簡単にまとめました.結構難しい(キャッシュされるためのフローなど)ですが,あやまると思わぬ事故を招きそうなためもう少し調査などして理解を深めたいと思います.

この記事をシェア