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-Range | If-None-Match | |
|---|---|---|
| 目的 | Range リクエストの安全な再開 | キャッシュの検証 |
| 不一致時 | 200 OK(全体を返す) | 200 OK(新しいコンテンツを返す) |
| 一致時 | 206 Partial Content | 304 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 との比較
| ETag | Last-Modified | |
|---|---|---|
| 精度 | コンテンツ変更を確実に検出 | 秒単位(同一秒内の変更を見逃す) |
| 実装コスト | ハッシュ計算が必要 | タイムスタンプのみ |
| 信頼性 | 高 | 中 |
両方返しておくと互換性が上がる。
Cache-Control との組み合わせ
Cache-Control: max-age=3600
ETag: "abc123"
max-age の間はキャッシュをそのまま使い、期限切れ後は If-None-Match で検証する。
分散サーバーでの注意点
サーバーごとに異なる ETag を生成すると条件付きリクエストが誤動作する。
対策:
- コンテンツのハッシュ(MD5、SHA など)を ETag に使う(サーバー ID は含めない)
- または弱い ETag を使う