This document recommends a two-step process for accessing resources that have indeterminate-length representations.
Two steps are necessary because of limitations with the range request header fields and the Content-Range response header fields. A server cannot know from a range request that a client wishes to receive a response that does not have a definite end. More critically, the header fields do not allow the server to signal that a resource has indeterminate length without also providing a fixed portion of the resource.
A client first learns that the resource has a representation of indeterminate length by requesting a range of the resource. The server responds with the range that is available but indicates that the length of the representation is unknown using the existing Content-Range syntax. See
Section 2.1 for details and examples.
Once the client knows the resource has indeterminate length, it can request a range with a very large end position from the resource. The client chooses an explicit end value larger than can be transferred in the foreseeable term. A server that supports range requests of indeterminate length signals its understanding of the client's indeterminate range request by indicating that the range it is providing has a range end that exactly matches the client's requested range end rather than a range that is bounded by what is currently available. See
Section 2.2 for details.
Determining if a representation is continuously aggregating ("live") and determining the randomly accessible byte range can both be performed using the existing definition for an open-ended byte-range request. Specifically,
Section 2.1 of
RFC 7233 defines a byte-range request of the form:
byte-range-spec = first-byte-pos "-" [ last-byte-pos ]
which allows a client to send a HEAD request with a first-byte-pos and leave last-byte-pos absent. A server that receives a satisfiable byte-range request (with first-byte-pos smaller than the current representation length) may respond with a 206 status code (Partial Content) with a Content-Range header field indicating the currently satisfiable byte range. For example:
HEAD /resource HTTP/1.1
Host: example.com
Range: bytes=0-
returns a response of the form:
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1234567/*
from the server indicating that (1) the complete representation length is unknown (via the "*" in place of the complete-length field) and (2) only bytes 0-1234567 were accessible at the time the request was processed by the server. The client can infer from this response that bytes 0-1234567 of the representation can be requested and transfer can be performed immediately.
Once a client has determined that a representation has an indeterminate length and established the byte range that can be accessed, it may want to perform a request with a start position within the randomly accessible content range and an end position at an indefinite/live point -- a point where the byte-range GET request is fulfilled on-demand as the content is aggregated.
For example, for a large video asset, a client may wish to start a content transfer from the video "key" frame immediately before the point of aggregation and continue the content transfer indefinitely as content is aggregated, in order to support low-latency startup of a live video stream.
Unlike a byte-range request header field, a byte-content-range response header field cannot be "open-ended", per
Section 4.2 of
RFC 7233:
byte-content-range = bytes-unit SP
( byte-range-resp / unsatisfied-range )
byte-range-resp = byte-range "/" ( complete-length / "*" )
byte-range = first-byte-pos "-" last-byte-pos
unsatisfied-range = "*/" complete-length
complete-length = 1*DIGIT
Specifically, last-byte-pos is required in byte-range. So, in order to preserve interoperability with existing HTTP clients, servers, proxies, and caches, this document proposes a mechanism for a client to indicate support for handling an indeterminate-length byte-range response and a mechanism for a server to indicate if/when it's providing an indeterminate-length response.
A client can indicate support for handling indeterminate-length byte-range responses by providing a very large value for the last-byte-pos in the byte-range request. For example, a client can perform a byte-range GET request of the form:
GET /resource HTTP/1.1
Host: example.com
Range: bytes=1230000-999999999999
where the last-byte-pos in the request is much larger than the last-byte-pos returned in response to an open-ended byte-range HEAD request, as described above, and much larger than the expected maximum size of the representation. See
Section 6 for range value considerations.
In response, a server may indicate that it is supplying a continuously aggregating/live response by supplying the client request's last-byte-pos in the Content-Range response header field.
For example:
GET /resource HTTP/1.1
Host: example.com
Range: bytes=1230000-999999999999
returns
HTTP/1.1 206 Partial Content
Content-Range: bytes 1230000-999999999999/*
from the server to indicate that the response will start at byte 1230000 and continue indefinitely to include all aggregated content, as it becomes available.
A server that doesn't support or supply a continuously aggregating/live response will supply the currently satisfiable byte range, as it would with an open-ended byte request.
For example:
GET /resource HTTP/1.1
Host: example.com
Range: bytes=1230000-999999999999
returns
HTTP/1.1 206 Partial Content
Content-Range: bytes 1230000-1234567/*
from the server to indicate that the response will start at byte 1230000, end at byte 1234567, and not include any aggregated content. This is the response expected from a typical HTTP server -- one that doesn't support byte-range requests on aggregating content.
A client that doesn't receive a response indicating it is continuously aggregating must use other means to access aggregated content (e.g., periodic byte-range polling).
A server that does return a continuously aggregating/live response should return data using chunked transfer coding and not provide a Content-Length header field. A 0-length chunk indicates the end of the transfer, per
Section 4.1 of
RFC 7230.