要約

  • HTTP 206 は、選択された表現のうち宣言された一つ以上の範囲が正常に届いたことを示すが、別々に取得した範囲が一つの完全なオブジェクトを作ることまでは示さない。
  • 再開転送とキャッシュでの結合には、共通の強いバリデータ、正確な区間被覆、表現全体に対する最終整合性検査が必要だ。
  • 206 応答の Content-Length は通常そのメッセージ本文の長さであり、Content-Range が位置と選択表現の完全長を示す。
  • 完了率ではなく、版の同一性と受け入れた全区間を残す「範囲組み立てレシート」が必要になる。

オブジェクトストレージからルーティングデータのアーカイブを取得する場面を考える。通信が途中で切れ、クライアントが残りを要求する前に、オリジンが同程度の大きさの新しいスナップショットへ差し替えた。どちらの要求も 206 で成功し、要求した区間はすべて届き、バイト数も予定値に達する。それでも完成ファイルは旧版の前半と新版の後半を混ぜている。再試行を同じ強いバリデータに結び付けなかったからだ。

これは仮想的な運用例であり、特定事業者の障害を述べるものではない。HTTP には防止手段がある。問題は、部分応答に全体の証明まで求める運用にある。

Range 成功の意味は限定される

RFC 9110 は 206 Partial Content を、選択された表現の一部を一つ以上転送して Range リクエストを正常に満たした状態と定義する。サーバーは記載された区間を渡したと主張するのであって、クライアントが表現全体を持ったとは主張しない。

受信側は Content-Type と各 Content-Range を調べ、どの部分が含まれ、追加要求が必要かを判断しなければならない。単一区間なら Content-Range が両端と通常は完全長を示す。Content-Length は現在の 206 メッセージに含まれるオクテット数を表す。両者を混同すれば、正しい部分応答が誤った完了シグナルになる。

複数区間では返却順が要求順と異なることがあり、サーバーが区間をまとめたり、満たせない区間を除外したりもする。したがって被覆は実際に返った区間から計算し、要求順、応答数、進捗バーから推測してはならない。

継続性は URL ではなく表現に属する

URL が同じでもバイトが同じとは限らない。コンテンツネゴシエーション、デプロイ、生成時刻、オリジン更新によって、対象 URI を保ったまま選択表現は変わる。安全な再開には、新旧の断片が同じ版である証拠が要る。

If-Range はこの境界を守る。クライアントはバリデータを添えて残りの範囲を要求できる。一致すればサーバーは部分を返し、不一致なら Range を無視して新しい表現全体を返す。RFC 9110 は If-Range に弱い ETag を使うことを禁じる。バイト単位で結合できる表現を区別する強い比較が必要だからだ。

従って If-Range 後の 200 は、206 に戻すべき非効率な失敗ではない。以前の断片を安全に延長できないという証拠であり、古い組み立て状態を捨てて新しい完全表現へ置き換えるべき場面である。

キャッシュも同じ義務を負う

RFC 9111 は、キャッシュが後続の Range 転送で不完全な応答を完成させることを認める。ただし、すべての範囲が同じ強いバリデータを共有し、部分コンテンツの結合規則に従う場合に限られる。

キャッシュヒット率や保存済みバイト量だけでは足りない。キャッシュキーとネゴシエーション条件、各区間のバリデータ、最新応答によるヘッダー更新、組み立て済み応答が新鮮か再検証済みか、または明示的に stale 提供を許されたかを記録する必要がある。断片を保存するダウンロード管理、ミラー、ストレージゲートウェイも同じ問題を持つ。

正しい層で整合性を検査する

RFC 9530 は、HTTP メッセージのコンテンツに対する Content-Digest と、選択された表現データ全体に対する Repr-Digest を分けている。206 では前者が受信セグメントを、後者が複数要求や接続から復元した完成オブジェクトを検査できる。

ダイジェストはバリデータの代わりではない。バリデータは断片の版が同じことを示し、Repr-Digest は最終バイトを検査し、区間表は合計値に隠れた欠落や重複がないことを示す。また整合性フィールドは認証、認可、プライバシーを定義しない。R063 が扱うのは、取得バイトが一つの一貫した表現を形成したかという限定された問いである。

範囲組み立てレシートを作る

最初の部分応答を受け入れた時点でレシートを開く。対象 URI、メソッド、選択に影響する要求ヘッダー、コンテンツエンコーディング、メディアタイプ、完全長、強いバリデータ、観測時刻、そしてオリジン、中継、ローカル保存のどこから来たかを固定する。

各部分について、実際の区間、ステータス、バリデータ、取得元、キャッシュ状態、利用できる場合はセグメントダイジェストを残す。区間集合を正規化し、重複で進捗を水増しせず、欠落を可視化する。凍結した表現の識別情報と矛盾する断片は拒否する。

区間が表現を正確に覆い、再構成したバイトが期待する Repr-Digest または独立取得したハッシュと一致した時だけ閉じる。強いバリデータが変わる、失われる、曖昧になる場合は混成状態を破棄し、現在の完全表現を取得し直す。帯域は余分に使うが、「処理したオブジェクトが一つの版として実在した」という価値の高い主張を守れる。

情報源