HTTP 範囲リクエスト

HTTP 範囲リクエストでは、サーバーからクライアントに HTTP メッセージの一部のみを送信できます。部分リクエストは、たとえば、大きなメディアや、一時停止や再開機能を持つファイルのダウンロードに役立ちます。

サーバーが部分リクエストに対応しているかどうかの確認

Accept-Ranges が HTTP レスポンスに存在した場合 (そして値が "none" ではない場合)、サーバーは範囲リクエストに対応しています。これは例えば、 HEAD リクエストを cURL で発行することで確認することができます。

curl -I http://i.imgur.com/z4d4kWk.jpg

HTTP/1.1 200 OK
...
Accept-Ranges: bytes
Content-Length: 146515

このレスポンスの中で、 Accept-Ranges: bytes は範囲を定義する単位としてバイト数が使えることを示しています。ここで Content-Length ヘッダーも受け取る画像の全体の長さを示すので有用です。

サイトが Accept-Ranges ヘッダーを省略した場合は、おそらく部分リクエストに対応していません。サイトにとっては値として明示的に "none" を送信して、対応がないことを示すこともあります。アプリによっては、このような場合にダウンロードマネージャーが一時停止ボタンを無効化します。

curl -I https://www.youtube.com/watch?v=EwTZ2xpQwpA

HTTP/1.1 200 OK
...
Accept-Ranges: none

サーバーからの特定の範囲のリクエスト

サーバーが範囲リクエストをサポートしている場合、そのリクエストをRangeで発行することができ、それはサーバーが返すべきドキュメントの一部分を指し示しています。

単一部分のリクエスト

リソースから単一の範囲を要求することが可能です。ここで再び、cURLを用いてこれを検証することができます。"-H"オプションはリクエストに対して、この場合、最初の1024バイトを要求するRange ヘッダーラインを付け加えることができます。

curl http://i.imgur.com/z4d4kWk.jpg -i -H "Range: bytes=0-1023"

発行されるリクエストは次のようになります:

GET /z4d4kWk.jpg HTTP/1.1
Host: i.imgur.com
Range: bytes=0-1023

サーバーは 206 Partial Content ステータスコードとともに以下のレスポンスを返します:

HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/146515
Content-Length: 1024
...
(binary content)

Content-Length はここでの場合、要求された範囲の大きさを返します(画像全体の大きさではありません)。 Content-Range レスポンスヘッダーはこの部分的なメッセージが全体のリソースのうちのどの部分に属しているのかを指し示しています。

複数部分のリクエスト

Range ヘッダーはまた、ドキュメントの複数の範囲を一度に取得する手段も提供しています。それら複数の範囲はカンマで区切ることで指定できます。

curl http://www.example.com -i -H "Range: bytes=0-50, 100-150"

サーバーは 206 Partial Content ステータスコードと Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5 ヘッダを伴ってレスポンスを返し、そこでは指定した複数のバイト範囲に関するデータが後ろに続いていることがわかります。 各々のバイト範囲において対応する Content-Type と Content-Range ヘッダーフィールドが含まれており、それぞれのボディ部分を区切るための境界文字列が境界パラメーターによって指定されています。

HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5
Content-Length: 282

--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 0-50/1270

<!doctype html>
<html>
<head>
    <title>Example Do
--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 100-150/1270

eta http-equiv="Content-type" content="text/html; c
--3d6b6a416f9b5--

条件付き範囲リクエスト

リソースのさらなる部分に対してリクエストを再開する際、最後にバイト範囲の断片を受け取ったときから、サーバー側で格納されているリソースが変更されていないことを保証する必要があります。

If-Range HTTPリクエストヘッダは範囲リクエストに対して条件付けを付与することができます。条件が満たされた場合、範囲リクエストが発行され、サーバーは適切なボディとともに 206 Partial Content ステータスを返します。もし条件が満たされなかった場合、全てのリソースが 200 OK ステータスとともに返されます。このヘッダは Last-Modified validatorあるいは ETag を伴って用いられます。両方を同時に使うことはありません。

If-Range: Wed, 21 Oct 2015 07:28:00 GMT 

部分的なリクエストのレスポンス

範囲リクエストを用いる際、これに関連した3つのステータスコードが存在します。

  • 範囲リクエストが成功した際 206 Partial Content ステータスコードがサーバーから返されます。
  • 範囲リクエストが元のリソースの境界を越え出た場合 (つまり範囲を示す値がリソースより外にはみ出た場合) 、サーバーは 416 Requested Range Not Satisfiable ステータスコードを返します。
  • 範囲リクエストがサポートされていない場合、サーバーから 200 OK ステータスコードが返されます。

チャンク Transfer-Encoding との比較

Transfer-Encoding ヘッダーを用いることでチャンクごとのエンコーディングが可能になります。これは大きいサイズのデータがクライアントに送られ、リクエストが完全に処理されるまでレスポンス全体のサイズが判明しない場合に有用です。サーバーはクライアントに対して、バッファリングも実際の大きさも確かめることなく、即座にデータを送ります。これはレイテンシーの向上に導きます。範囲リクエストとチャンクの使用は共用可能であり、互いに指定されていようといなかろうと気にせず使用することが可能です。

関連情報