要約

  • 304 Not Modified は、選択された表現に対するHTTP条件を評価し、キャッシュが保存済みメタデータを更新できるようにする応答である。上流依存関係全体の鮮度証明ではない。
  • 重要な判断に再検証結果を用いるなら、バリデーターを、その表現を生成したデータスナップショットやポリシーの版と結び付ける必要がある。

データベースのスナップショットから設定を返すエンドポイントを考える。キャッシュは保持しているエンティティタグを If-None-Match に入れて送る。オリジンは選択された表現について条件を評価し、304 Not Modified を返す。新しい表現内容は転送されない。キャッシュは仕様に従ってメタデータを更新し、運用画面は緑色の再検証イベントを「依存関係全体を検証済み」と表示する。

ここでプロトコルの証拠が経営上の虚構に変わる。アプリケーションが使ったスナップショットが業務判断の許容範囲より古くても、304自体は正しい場合がある。HTTPは与えられた問いに答えた。画面の側が別の問いへすり替えたのである。

条件が対象とするもの

RFC 9110は If-None-Match を、選択された表現のエンティティタグとの関係で定義する。条件付きGETまたはHEADで条件が偽なら、内容を伴うはずだった200の代わりに304が返る。この仕組みの価値は意味が限定されている点にある。対象表現に対して、HTTPの規則どおりに条件が評価されたということだ。

304は「空の200」ではない。内容は持たないが、必要に応じて ETag、Date、Cache-Control、Expires、Content-Location、Vary など、キャッシュを導くフィールドを返す。RFC 9111は、更新対象となる保存済みレスポンスの特定方法も定める。強いバリデーターと弱いバリデーターの役割は同一ではない。対応するレスポンスを特定すると、仕様上の除外を守りつつ、304の該当フィールドで保存済みヘッダーを更新する。

これは表現とそのメタデータに対する厳密な処理であって、その表現に影響したすべてのシステムの状態を宣言するものではない。

表現の有効性と依存関係の新しさは別物

エンティティタグは、オリジンが選んだ表現の意味付けに属する。アプリケーションは最終バイト列、版番号、デプロイ識別子、または実装固有の入力からタグを生成できる。すべてのデータベース行、ポリシーバンドル、機能フラグ、権限フィード、上流API結果の版をタグへ含めるよう、HTTPが要求しているわけではない。

派生表現では、この差が重要になる。JSONのバイト列が保存時から変わらず、304が正しいことはあり得る。しかし、そのバイト列が5分前に更新されるべきだったスナップショットから作られていたなら、変化のない表現は、発見すべき古さをそのまま保存している。再検証はバリデーターの境界内で継続性を確認するだけで、その境界を後から広げない。

条件付きリクエストを否定する議論ではない。転送量と計算量を減らす重要な仕組みであり、すべての304が古いデータを隠すわけでもない。論点は証拠の範囲だ。「表現がこのバリデーターと一致する」は、追加証拠なしに「すべての依存関係が最新である」へ変換できない。

欠けた来歴を残す

影響の大きい設定レスポンスでは、依存スナップショットの識別子、ソース更新時刻、ポリシーバンドルの版、マテリアライズのウォーターマークを公開または記録できる。キャッシュ側はリクエスト対象、保存済みレスポンス、条件フィールド、304メタデータ、結果を利用した判断を保存できる。

ここで提案する検証チェーンのレシートは、編集上の統制を整理したものであり、IETFや引用したRFCが定義するプロトコルオブジェクトではない。少なくとも次を結び付けるべきだ。

  • リクエスト対象と選択された表現の識別子
  • バリデーターの種類と値、条件付きリクエストのフィールド
  • 304の時刻、ステータス、返されたメタデータ
  • 更新対象の保存済みレスポンスと更新フィールド
  • 表現生成に使った上流スナップショット、規則、依存関係の版
  • その結果に依存した判断、制御、または自動処理

依存関係の版を表現へ結び付けられない場合、誠実な表示は「表現は再検証済み、依存関係の新しさは不明」である。緑色の一語より狭いが、判断にははるかに役立つ。

情報源