ゆるテックノート

メソッドとキャッシュの関係

「このレスポンス、キャッシュされる?」を素早く判断するためのメモです。RFC 9110のキャッシュ仕様に合わせて、GET/HEAD/POSTの扱いをまとめました。

キャッシュの基本

HTTPキャッシュはメソッドとヘッダーの組み合わせで決まります。特にGET/HEADは明示がなければキャッシュ対象になり得ます。

メソッド別の前提

メソッド キャッシュ扱い ポイント
GET 対象 レスポンスがshared cacheに載る前提。Cache-Controlで寿命を決める。
HEAD 対象 GETと同じ扱い。ボディなし。
POST 原則非対象 Cache-ControlやExpiresが明示され、かつステータスがキャッシュ可能な場合にのみ格納可(実務ではまれ)。
PUT/PATCH/DELETE 対象外 ステート変更用のため格納されない(仕様ではキャッシュ無効)。

主なキャッシュ制御ヘッダー

レスポンスヘッダーがキャッシュの寿命や共有可否を決めます。

ヘッダーまとめ

  • Cache-Control: max-age, s-maxage, no-cache, no-store, private, must-revalidate などで寿命と再検証ルールを指定。
  • ETag/Last-Modified: 再検証に使うタグや日時。条件付きリクエストとセットで運用。
  • Vary: Accept-Language, Authorization など、レスポンスが依存するリクエストヘッダーを列挙。CDNキャッシュでも必須。
  • Expires: 旧式の期限指定。Cache-Controlが優先されるが併記されることが多い。

POSTレスポンスをキャッシュするとき

仕様上は可能ですが、条件が多いので意図しないキャッシュを避ける設定も重要です。

成立条件

  • ステータスがキャッシュ可能(例: 200, 203, 204, 206, 300, 301, 404, 410など)であること。
  • Cache-Controlに明示的に保存を許可する指示があること(public, max-age など)。
  • Varyで適切に分岐を示すこと。示さないと別ユーザーの応答が混ざる恐れ。
  • ボディがユーザー固有ならprivateを付けてshared cacheに載らないようにする。

避けたい場合

  • Cache-Control: no-store を明示。機密データやトークン発行系では必須。
  • Authorization付きリクエストはshared cacheではキャッシュ禁止がデフォルト(RFC 9110 13.5.2)。必要ならpublicを付けるが慎重に。

再検証と無効化

GET/HEADは条件付きリクエストを活用し、変更時だけ再取得するのが効率的です。

再検証のコツ

  • ETagを返し、If-None-Matchで304を返せるようにする。
  • キャッシュを必ず避けたいエンドポイントではCache-Control: no-storeまたはCache-Control: no-cache, max-age=0を付ける。
  • Invalidate時は適切なバージョンアップ(ETag更新)か、Cache-Control: no-cacheで再検証を強制する。

まとめ

「GET/HEADはキャッシュ前提」「POSTは明示しない限りキャッシュされない」が基本線。Cache-ControlとETagを正しく返し、必要に応じてno-storeで締めておくと安心です。