Range

Range: ヘッダー (HTTP)

[9] Range: ヘッダーは、資源の一部分だけを応答に含めるべきことを指定するものです。

[36] HTTP ではバイト単位で実体の一部を取得する方法が、 RTSP では時刻を指定する方法が標準化されています。 大きなファイルの転送を分割して行ったり、 分割再生可能に設計された音声動画を途中から取得して再生するなどの実装が可能になります。

[37] HTTP では Range: ヘッダーGET 要求でのみ使えます。

仕様書

意味

[20] GET 要求における Range: ヘッダーは、選択された表現のデータの1つ以上の部分範囲のみを転送することを求めるものです >>14

構文

[21] 値は範囲単位=範囲単位依存の値を並べたものです >>14

[22] 範囲単位依存の値の構文はそれぞれの範囲単位の仕様によります。 ただし VCHAR (U+0021-U+007E) の文字の1つ以上の列とされています。 >>14

  1. 範囲単位
  2. =
  3. +
    1. U+0021-U+007E

[27] クライアントは、対象となるデータを含む部分全体を1つの範囲とした場合よりも処理や転送が非効率な形の複数の範囲の要求を送信するべきではありません >>14

[28] 例えば bytes 10-12,50-55,30-40 のような指定よりは、 bytes 10-55 の方が適切と思われます。

[29] クライアントは特に事情がない限り昇順範囲を並べるべきです >>14

[39] クライアントは、 multipart/byteranges に対応していない場合、 複数の範囲を指定してはなりません >>38

処理モデル

[41] 範囲要求不完全メッセージを参照。

歴史

[15] RFC 2068 (HTTP/1.1) 14.36・RFC 2616 (HTTP/1.1) 14.35 Range

RFC 2068 14.36.1・RFC 2616 14.35.1 Byte Ranges

Since all HTTP entities are represented in HTTP messages as sequences of bytes, the concept of a byte range is meaningful for any HTTP entity. (However, not all clients and servers need to support byte-range operations.)

HTTP 実体は HTTP メッセージ中ではすべてバイト列として表現されますから、 任意の HTTP 実体に対してバイト範囲という概念が意味を持ちます。 (しかし、すべてのクライアントと鯖がバイト範囲操作に対応する必要はありません。)

Byte range specifications in HTTP apply to the sequence of bytes in the entity-body (not necessarily the same as the message-body).

HTTP でのバイト範囲指定は、 entity-body (必ずしも message-body と同じではない。) のバイト列に適用します。

A byte range operation may MAY specify a single range of bytes, or a set of ranges within a single entity.

バイト範囲操作は単一の範囲か、または単一の実体内の範囲の集合を指定して構いません

  • ranges-specifier = byte-ranges-specifier
  • byte-ranges-specifier = bytes-unit "=" byte-range-set
  • byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec )
  • byte-range-spec = first-byte-pos "-" [last-byte-pos]
  • first-byte-pos = 1*DIGIT
  • last-byte-pos = 1*DIGIT

The first-byte-pos value in a byte-range-spec gives the byte-offset of the first byte in a range. The last-byte-pos value gives the byte-offset of the last byte in the range; that is, the byte positions specified are inclusive. Byte offsets start at zero.

byte-range-specfirst-byte-pos 値は、範囲中の最初のバイトのバイト offset を与えます。 last-byte-pos 値は範囲中の最後のバイトのバイト offset を与えます。つまり、指定されたバイト位置は範囲に含まれます。 バイト offset は零から始めます。

If the last-byte-pos value is present, it must MUST be greater than or equal to the first-byte-pos in that byte-range-spec, or the byte-range-spec is syntactically invalid. The recipient of a byte-range-set that includes one or more syntactically an invalid byte-range-spec values MUST must ignore it the header field that includes that byte-range-set.

last-byte-pos 値が示されるときは、その byte-range-specfirst-byte-pos 以上でなければなりません。 そうでなければ構文的に不当です。一つ以上の構文的に不正な byte-range-spec 値を含む byte-range-set の受信者は、その byte-range-set を含む頭欄を無視しなければなりません

If the last-byte-pos value is absent, or if the value is greater than or equal to the current length of the entity-body, last-byte-pos is taken to be equal to one less than the current length of the entity-body in bytes.

last-byte-pos が欠けている場合、あるいは entity-body の現在の長さ以上のときは、 last-byte-pos は現在の entity-body のバイト長より一小さいものと取ります。

By its choice of last-byte-pos, a client can limit the number of bytes retrieved without knowing the size of the entity.

last-byte-pos を選ぶことにより、クライアントは実体の寸法を知らなくても取り出すバイト数を制限できます。

  • suffix-byte-range-spec = "-" suffix-length
  • suffix-length = 1*DIGIT

A suffix-byte-range-spec is used to specify the suffix of the entity-body, of a length given by the suffix-length value. (That is, this form specifies the last N bytes of an entity-body.) If the entity is shorter than the specified suffix-length, the entire entity-body is used.

suffix-byte-range-spec は、 entity-body の接尾部を suffix-length 値で与えた長さ分指定するのに使います。 (つまり、この書式は entity-body の最後の N バイトを指定します。) 実体が指定された suffix-length よりも短い場合には、 entity-body 全体を使います。

If a syntactically valid byte-range-set includes at least one byte-range-spec whose first-byte-pos is less than the current length of the entity-body, or at least one suffix-byte-range-spec with a non-zero suffix-length, then the byte-range-set is satisfiable. Otherwise, the byte-range-set is unsatisfiable. If the byte-range-set is unsatisfiable, the server SHOULD return a response with a status of 416 (Requested range not satisfiable). Otherwise, the server SHOULD return a response with a status of 206 (Partial Content) containing the satisfiable ranges of the entity-body.

構文的に妥当な byte-range-setentity-body の現在の長さより小さい first-byte-posbyte-range-spec を最低一つ含んでいる場合や、 非零 suffix-lengthsuffix-byte-range-spec を最低一つ含んでいる場合には、 byte-range-set は満足可能です。 そうでなければ、 byte-range-set は満足不能です。 byte-range-set が満足不能であれば、鯖は状態 416 (要求範囲満足不能) で応答を返すべきです。 そうでなければ、鯖は満足可能範囲の entity-body を含んだ 206 (部分内容) 状態で応答を返すべきです

Examples of byte-ranges-specifier values (assuming an entity-body of length 10000):

byte-ranges-specifier 値の例 (長さ 10000 の entity-body を仮定):

  • o - The first 500 bytes (byte offsets 0-499, inclusive): bytes=0-499
  • o - The second 500 bytes (byte offsets 500-999, inclusive): bytes=500-999
  • o - The final 500 bytes (byte offsets 9500-9999, inclusive): bytes=-500
  • o - Or bytes=9500-
  • o - The first and last bytes only (bytes 0 and 9999): bytes=0-0,-1
  • o - Several legal but not canonical specifications of the second 500 bytes (byte offsets 500-999, inclusive):
    • bytes=500-600,601-999
    • bytes=500-700,601-999

RFC 2068 14.36.2・RFC 2616 14.35.2 Range Retrieval Requests

HTTP retrieval requests using conditional or unconditional GET methods may MAY request one or more sub-ranges of the entity, instead of the entire entity, using the Range request header, which applies to the entity returned as the result of the request:

条件付または条件付でない GET 方式の HTTP 取り出し要求は、 要求の結果として返される実体に適用されるものである Range 要求頭を使って、 実体全体ではなく、実体の一つ以上の部分範囲を要求して構いません

  • Range = "Range" ":" ranges-specifier

A server MAY ignore the Range header. However, HTTP/1.1 origin servers and intermediate caches SHOULD ought to support byte ranges when possible, since Range supports efficient recovery from partially failed transfers, and supports efficient partial retrieval of large entities.

鯖は、 Range 頭を無視しても構いません。 しかし、 HTTP/1.1 起点鯖中間キャッシュは、 可能な時にはバイト範囲に対応するべきです。なぜなら、 Range は部分的に失敗した転送から効率よく回復することや大きな実体の部分を効率的に取り出すことを支援するからです。

If the server supports the Range header and the specified range or ranges are appropriate for the entity:

  • o - The presence of a Range header in an unconditional GET modifies what is returned if the GET is otherwise successful. In other words, the response carries a status code of 206 (Partial Content) instead of 200 (OK).
  • o - The presence of a Range header in a conditional GET (a request using one or both of If-Modified-Since and If-None-Match, or one or both of If-Unmodified-Since and If-Match) modifies what is returned if the GET is otherwise successful and the condition is true. It does not affect the 304 (Not Modified) response returned if the conditional is false.

鯖が Range 頭に対応し、指定された範囲(群)がその実体について適当であるなら、

  • 条件付きでない GET での Range 頭の存在は、 GET が本来成功であるなら返されるものを修飾します。 言い換えれば、応答は状態符号 200 (了解) の代わりに 206 (部分内容) となります。
  • 条件付き GET (If-Modified-SinceIf-None-Match の一方又は両方、もしくは If-Unmodified-SinceIf-Match の一方又は両方を使った要求) での Range 頭の存在は、 GET が本来成功であって、条件が真であるなら返されるものを修飾します。 条件が偽であるときに返される 304 (未修正) 応答には影響しません。

In some cases, it may might be more appropriate to use the If-Range header (see section 14.27) in addition to the Range header.

場合によっては、 Range 頭に加えて If-Range 頭もあわせて使ったほうがより適切かもしれません。

If a proxy that supports ranges receives a Range request, forwards the request to an inbound server, and receives an entire entity in reply, it SHOULD only return the requested range to its client. It SHOULD store the entire received response in its cache, if that is consistent with its cache allocation policies.

範囲に対応したRange 要求を受信し、 上りサーバーに要求を転送し、返事の実体全体を受信したら、 クライアントには要求された範囲だけを返すべきです。 受信した応答がキャッシュ割当て方針に沿っているなら、 受信した応答全体をキャッシュに蓄積するべきです

地理的座標を指定する実装例

[7] Range: lats=; lons=100-120 "10.0N 20.0S 100.1E 120W" : Met-cast HTTP <http://zowie.metnet.navy.mil/~spawar/JMV-TNG/Met-Cast-HTTP.html#req.header.accept>。データを要求する地域を表すらしい。 HTTP/1.1 の一応用なんだけど、これじゃあ不適合じゃないのかね?

[17] Met-cast HTTP (oleg-at-pobox.com 著, 版) <http://okmij.org/JMV-TNG/Met-Cast-HTTP.html>

This header will be mandatory in version 2.0. It should tell the bounding box for an area on the globe for which data are requested.

[8] >>7 最後の引用文字列の部分が引数にしてあれば、 「HTTP/1.1 には不適合だけど RTSP を考慮しても整合性のある拡張だ」 とかなんとか好意的に評価することも可能だけど。。。

XPointer や RDQL を指定する実装例

[23] >>10 この論文では XPointer を使って資源の一部分を取り出す方法を提案しています。

Range: xpointer=element(a12)

結果は multipart/mixed で複数の XML 実体として返します。

XPointer scheme として RDF のグラフに照会するようなものを使う場合には単一の application/rdf+xml 実体として返す使い方もできます。

大変面白いアイデアですが、技術的問題点を指摘しておくなら、

  • もっと 822HTTP の全体と整合的であるように細かいところを詰める必要がある。
  • HTTP 頭欄では実質 US-ASCII しか安全に転送できない。 XPointerU+0000U+10FFFF の任意の文字を扱えるので、 どう折り合いをつけるのか。

などの問題を解決する必要があります。

[11] >>10 の論文の別の例は xpointer= が抜けた構文になっていて、 HTTP 的には最悪な状況になっています。

[12] search.cpan.org: Apache::XPointer - mod_perl handler to address XML fragments. <http://search.cpan.org/~ascope/Apache-XPointer-1.1/lib/Apache/XPointer.pm>

これは mod_perl を使った >>10-11 の実装です。 (まさに >>11 を使った最悪な。)

Apache::XPointer::XPathxpointer() を使って XML実体の一部を multipart/mixed で送ったり、独自の封筒でまとめて一つの XML 実体として送ったりできます。

Apache::XPointer::RDQLRDF のデータベースから RDQL による照会を使って RDF/XML 実体を取り出すことができます。 (Range の構文は更にひどくて、 XPointer ですらなく、単なる RDQL 直書きになってしまっています。) 結果は複数の application/rdf+xmlmultipart/mixed にしたり、一つにまとめて順序情報の RDF 文付きで得たりできます。 (名無しさん)

[13] Index of /javascript/xpointerhttprequest <http://aaronland.info/javascript/xpointerhttprequest/>

こちらは >>12 に対応する JavaScript の実装。

媒体向け

[18] RTSP では媒体の時間を指定することになっています。

[16] RFC 2326 (RTSP/1.0) 12.29 Range

This request and response header field specifies a range of time. The range can be specified in a number of units. This specification defines the smpte (Section 3.5), npt (Section 3.6), and clock (Section 3.7) range units. Within RTSP, byte ranges [H14.36.1] are not meaningful and MUST NOT be used. The header may also contain a time parameter in UTC, specifying the time at which the operation is to be made effective. Servers supporting the Range header MUST understand the NPT range format and SHOULD understand the SMPTE range format. The Range response header indicates what range of time is actually being played or recorded. If the Range header is given in a time format that is not understood, the recipient should return "501 Not Implemented".

[1] この要求・応答頭欄は時刻の範囲を指定します。 範囲は単位の数で指定出来ます。 この仕様書は smpte, npt, clock 範囲単位を定義します。 RTSP では、 byte 範囲には意味がなく、使用してはいけません。 この頭には time パラメーターも含めて、操作が有効となる UTC での時刻を指定しても構いません。 Range 頭に対応したサーバーは NPT 範囲形式を理解しなければならず、 SMPTE 範囲形式を理解するのが良いです。 Range 応答頭は実際に演奏又は録音されている時刻の範囲を示します。 Range 頭が理解不能な時刻形式で与えられている場合は、受信者は 「501 未実装」を返すのが良いです。

Ranges are half-open intervals, including the lower point, but excluding the upper point. In other words, a range of a-b starts exactly at time a, but stops just before b. Only the start time of a media unit such as a video or audio frame is relevant. As an example, assume that video frames are generated every 40 ms. A range of 10.0-10.1 would include a video frame starting at 10.0 or later time and would include a video frame starting at 10.08, even though it lasted beyond the interval. A range of 10.0-10.08, on the other hand, would exclude the frame at 10.08.

[2] 範囲は半分開間隔で、低位置は含んで高位置を含まないものです。 つまり、範囲-は丁度時刻に始まりますが、時刻の丁度前に止まります。 動画や音声の (frame) のような媒体単位の開始時刻だけが適切です。 例として、動画枠が 40 ms 毎に生成されるとします。範囲 10.0-10.110.0 かそれ以降の時刻に始まる動画枠を含み、 10.08 に始まる動画枠も (終わるのは間隔を超えますが) 含みます。 一方範囲 10.0-10.0810.08 の枠を除きます。

  • [3] Range = "Range" ":" 1\#ranges-specifier [ ";" "time" "=" utc-time ]
  • [4] ranges-specifier = npt-range | utc-range | smpte-range

訳注: >>3 にはゴミが入ってます。注意。 >>3-4 の時刻の定義については RFC 2326の日付形式, RFC 2326の時刻形式を参照。

Example:

  • [5] Range: clock=19960213T143205Z-;time=19970123T143720Z

The notation is similar to that used for the HTTP/1.1 [2] byte-range header. It allows clients to select an excerpt from the media object, and to play from a given point to the end as well as from the current location to a given point. The start of playback can be scheduled for any time in the future, although a server may refuse to keep server resources for extended idle periods.

[6] この記法は HTTP/1.1 の byte 範囲頭に使われているものと似ています。 これによりクライアントが媒体物体からの除外を選択出来、指定点から演奏して指定点で終えることや現在位置から指定点まで演奏することが出来ます。 録音再生の開始は将来のどの時刻にも予定出来ますが、サーバーは待機期間を延ばすためのサーバー資源の確保を拒むかもしれません。

[19] HTTP でも同様の指定を使う提案がありました。

実装

[823] RangeつきリクエストによるApacheのDoSとApache Killerの実力 | 水無月ばけらのえび日記 ( 版) <http://bakera.jp/ebi/topic/4512>

関連

[31] If-Range: ヘッダーを使って範囲要求に関する事前条件を指定できます。

[25] Issue 620386 - chromium - Range header vanishing when passed to fetch() - Monorail ( ()) <https://bugs.chromium.org/p/chromium/issues/detail?id=620386>

[24] Allow Range header to be set by APIs (jakearchibald著, ) <https://github.com/whatwg/fetch/commit/819d8c9d6617986a831ecd9cf21c34ba9589a890>

[26] Allow Range header to be set by APIs (jakearchibald著, ) <https://github.com/whatwg/fetch/commit/819d8c9d6617986a831ecd9cf21c34ba9589a890>

[30] Handling Partial Content / 206 · Issue #144 · whatwg/fetch () <https://github.com/whatwg/fetch/issues/144>

[32] Allow range header to be set by APIs by jakearchibald · Pull Request #560 · whatwg/fetch () <https://github.com/whatwg/fetch/pull/560>

[33] Specify identity encoding for range requests (jakearchibald著, ) <https://github.com/whatwg/fetch/commit/2f3d04d3713f6cd0f89d491217175b55911927be>

[34] Specify identity encoding for range requests (jakearchibald著, ) <https://github.com/whatwg/fetch/commit/2f3d04d3713f6cd0f89d491217175b55911927be>

[35] Some servers seem to expect 'Accept-Encoding : identity' to serve Range requests · Issue #747 · whatwg/fetch () <https://github.com/whatwg/fetch/issues/747>

[40] jakearchibald/accept-encoding-range-test () <https://github.com/jakearchibald/accept-encoding-range-test>

[42] Specify identity encoding for range requests. Fixes #747. by jakearchibald · Pull Request #751 · whatwg/fetch () <https://github.com/whatwg/fetch/pull/751>

[43] Additional reasoning for sending Accept-Encoding: identity by jakearchibald · Pull Request #764 · whatwg/fetch () <https://github.com/whatwg/fetch/pull/764>