⭐️304 ステータスコードと HTTP 条件付きリクエスト

If-None-Match: "abc" は「ETag が “abc” と一致しないなら本文をくれ」というお願い。 つまりここでの条件は「サーバーが本文を送るための条件」で、成否で返すものが変わる。

サーバー側の ETag条件レスポンス
"def"(変わっていた)一致しない → 成立200 + 本文
"abc"(変わっていない)一致した → 不成立304(本文なし)

304 は「条件が成立しなかったので 200 の代わりに返す返事」。 だから条件付きリクエストを送っていないのに 304 が返ることはない。

1回目: GET /style.css
       → 200 OK  ETag: "abc"  Cache-Control: max-age=600

max-age 経過 → キャッシュは stale になるが破棄はされない

2回目: GET /style.css   If-None-Match: "abc"
       → 304  ETag: "abc"   …本文なし・鮮度だけ更新
       or 200  ETag: "def"   …本文あり・差し替え

腹落ちポイントは キャッシュの期限切れ ≠ 再ダウンロード。 期限が切れたのは「確認せずに使ってよい期間」だけで、実体は手元に残っている(stale 状態)。 条件付きリクエストはそれを捨てずに「まだ使える?」と問い合わせだけする手段で、304 はその答え。 304 は Cache-Control を再送するのでキャッシュは fresh に戻る。

逆にバリデーターが無いレスポンスは確認手段がないので期限切れ = 再ダウンロード確定。つまり ETag を付けることは「キャッシュの寿命を延長する権利」を与えることに近い。