【実務・中級編】HTTP/1.1のRangeリクエストと206 Partial Content – HTTPプロトコル・通信規格実践ガイド

巨大ファイルを「切り出す」技術:HTTP/1.1 Rangeリクエストの深淵

ネットワークエンジニアとして現場に立っていると、時に「なぜブラウザの動画再生はあんなにスムーズなのか」「なぜ中断されたダウンロードが再開できるのか」という問いに直面します。その答えの鍵を握るのが、HTTP/1.1で導入されたRangeリクエストと、その応答である206 Partial Contentです。

これは単なる「一部取得」の機能ではありません。限られた帯域を効率的に使い、ユーザーエクスペリエンスを最大化するための、プロトコル設計の美学が詰まった仕組みなのです。今日は、この「断片化」の魔術を紐解いていきましょう。

—

1. なぜ「全部」受け取らないのか?

HTTP/1.0の頃、クライアントがファイルの一部だけを欲しがった場合、サーバーはファイル全体を一度に送るしかありませんでした。もし5GBの動画の最後10秒だけが必要でも、サーバーは5GB全てを網にかけ、回線を占有していたのです。

これを解決したのがHTTP/1.1のRangeヘッダーです。クライアントがサーバーに対して「ファイルのこのオフセットからこのオフセットまでだけ頂戴」と指示を送る。サーバーはそれに対して「承知した。要求された部分だけを送る」と応える。このやり取りにより、無駄なトラフィックが劇的に削減されました。

206 Partial Contentの正体

サーバーが要求された範囲を正しく理解し、一部データのみを返したとき、ステータスコードは `200 OK` ではなく `206 Partial Content` になります。この「206」こそが、サーバーが「この応答は全体の一部です」と明示する合図です。

—

2. 通信のフローとヘッダーの解剖

実際にどのようなやり取りが行われているのか、そのシーケンスを見てみましょう。

クライアントからの要求(Rangeヘッダー)

クライアントは `Range` ヘッダーを用いて、バイト単位で範囲を指定します。

GET /video.mp4 HTTP/1.1
Host: example.com
Range: bytes=0-1023 # 最初の1024バイトを要求

サーバーからの応答(206とContent-Range)

サーバーは、応答ヘッダーに `Content-Range` を付与して返します。ここがデバッグ時の肝です。

HTTP/1.1 206 Partial Content
Content-Type: video/mp4
Content-Length: 1024
Content-Range: bytes 0-1023/5000000 # 「0〜1023バイト目。全体のサイズは500万バイト」

この `Content-Range` の書式 `bytes <開始>–<終了>/<総サイズ>` を見れば、クライアントは「あとどれくらい残っているか」を正確に把握できます。これがレジューム(中断再開)機能の心臓部です。

—

3. 実務で役立つ実装・デバッグTips

理論が分かったところで、実務での検証方法をいくつか紹介します。トラブルシュートの際、まずはこれらを試すのが私の鉄板です。

curlで「切り出し」をテストする

ネットワークの疎通確認には `curl` を使うのが最も確実です。以下のコマンドでサーバーがRangeリクエストをサポートしているか確認できます。

-Iでヘッダーのみを取得し、Accept-Rangesを確認する
curl -I https://example.com/large-file.zip

実際に特定の範囲をダウンロードしてファイルサイズを確認する
curl -r 0-1023 -o part.bin https://example.com/large-file.zip
ls -l で part.bin が 1024バイトであることを確認

Python (Requests) で実装する場合

API設計において、クライアント側から動的に範囲を指定して取得するコードはこうなります。

import requests

url = “https://example.com/data.bin”
headers = {‘Range’: ‘bytes=0-1023’} # 最初の1KBを指定

response = requests.get(url, headers=headers)

if response.status_code == 206:
print(f”成功: {len(response.content)} バイトを取得しました”)
else:
print(f”ステータスコード: {response.status_code}”)

Webサーバー(Nginx)の設定確認

もしサーバーが206を返さない場合は、Nginxの設定を確認してください。デフォルトでは有効ですが、キャッシュ設定などで阻害されていることがあります。

NginxでRangeリクエストを許可する設定
基本的にデフォルトで有効だが、proxy_cache等を使用している場合は注意が必要
location / {
# プロキシ先がRangeをサポートしている場合、そのまま転送する設定
proxy_set_header Range $http_range;
proxy_set_header If-Range $http_if_range;
}

—

4. エンジニアとしての視点:落とし穴には注意

最後に、現場でよくある落とし穴を一つ。`If-Range` ヘッダーの存在です。

もしファイルをダウンロードしている最中にサーバー上のファイルが更新されてしまったら?オフセットだけを指定して取得すると、データが壊れてしまいます。これを防ぐのが `If-Range` です。ETagやLast-Modifiedを条件に指定することで、「ファイルが更新されていれば最初から、そうでなければ続きから」という賢い制御が可能になります。

単に「動けばいい」ではなく、「なぜそのヘッダーが必要なのか」を深掘りすること。それが、障害に強いインフラを構築するエンジニアへの第一歩です。

皆さんのシステムでも、まずはブラウザのデベロッパーツールを開いて、動画サイトの通信を眺めてみてください。206の波が次々と押し寄せてくる様子が見えるはずです。それが、現代のWebを支える「断片化」の鼓動なのです。

コメント

タイトルとURLをコピーしました