HTTP 条件付きリクエスト メモ

リソースの特定バージョンを識別する HTTP ヘッダー。リソースのフィンガープリントとして機能し、キャッシュの有効性検証や楽観的ロックに使われる。RFC 7232 で規定。

強い ETag と弱い ETag

ETag: "abc123"       # 強い ETag:バイト単位で完全一致を保証
ETag: W/"abc123"     # 弱い ETag:セマンティック上の等価性のみ保証

強い ETag はバイト完全一致を保証するため Range リクエストに使えるが、全バイトのハッシュ計算が必要で生成コストが高い。また分散環境(複数サーバーが同じ URL を処理する構成)では、サーバーごとに異なる値を生成してしまい ETag が一致しなくなる問題が起きやすい。

弱い ETag は Range リクエストには使えないが、ファイルサイズや更新タイムスタンプなど全サーバーで共有しやすい情報から生成できるため、分散環境での値の統一が容易。

Range リクエスト

ファイルの一部分だけを取得する HTTP リクエスト。サーバーが対応している場合、Accept-Ranges: bytes ヘッダーをレスポンスに含める。

# クライアント(先頭 1024 バイトだけ取得)
GET /video.mp4 HTTP/1.1
Range: bytes=0-1023

# サーバー
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/10485760
Content-Length: 1024

主なユースケース:

  • 動画・音声のシーク(再生位置の移動)
  • 大きなファイルのダウンロード再開(レジューム)
  • 並列ダウンロード(複数の範囲を同時取得)

If-Range(条件付き Range リクエスト)

「ETag が一致するなら指定範囲だけ返し、一致しないならファイル全体を返す」というリクエスト。ダウンロードの途中再開で、再開前にリソースが変わっていないかを確認するのに使う。

GET /video.mp4 HTTP/1.1
Range: bytes=1024-2047
If-Range: "abc123"

# ETag が一致 → 指定範囲だけ返す
HTTP/1.1 206 Partial Content

# ETag が不一致 → 全体を返す(エラーにはならない)
HTTP/1.1 200 OK

If-Range には強い ETag か Last-Modified の値を指定する。弱い ETag は「バイト単位の完全一致」を保証しないため使用不可。

If-None-Match との違い

If-RangeIf-None-Match
目的Range リクエストの安全な再開キャッシュの検証
不一致時200 OK(全体を返す)200 OK(新しいコンテンツを返す)
一致時206 Partial Content304 Not Modified
弱い ETag使用不可使用可

If-Range は不一致でもエラーにならないのがポイント。不一致なら全体を返すことで、ダウンロードが壊れた状態になるのを防ぐ。

条件付きリクエスト

If-None-Match(キャッシュバリデーション)

# クライアント
GET /resource HTTP/1.1
If-None-Match: "abc123"

# サーバー(変更なし)
HTTP/1.1 304 Not Modified

# サーバー(変更あり)
HTTP/1.1 200 OK
ETag: "def456"

If-Match(楽観的ロック)

# クライアント
PUT /resource HTTP/1.1
If-Match: "abc123"

# サーバー(ETag 不一致=他者が更新済み)
HTTP/1.1 412 Precondition Failed

Lost Update 問題(他のクライアントが先に更新した場合の上書き)を防ぐのに使える。

Last-Modified との比較

ETagLast-Modified
精度コンテンツ変更を確実に検出秒単位(同一秒内の変更を見逃す)
実装コストハッシュ計算が必要タイムスタンプのみ
信頼性

両方返しておくと互換性が上がる。

Cache-Control との組み合わせ

Cache-Control: max-age=3600
ETag: "abc123"

max-age の間はキャッシュをそのまま使い、期限切れ後は If-None-Match で検証する。

分散サーバーでの注意点

サーバーごとに異なる ETag を生成すると条件付きリクエストが誤動作する。

対策:

  • コンテンツのハッシュ(MD5、SHA など)を ETag に使う(サーバー ID は含めない)
  • または弱い ETag を使う