Subject: Range response with empty content

From: "A. Rothman" <[email-masked]>
Date: Thu, 23 Jul 2015 22:16:41 +0300

Hi,

I'd like to suggest that RFC 7233 (or whatever will succeed it) should 
mention explicitly how a server should respond to a Range request when 
the requested resource has no content (e.g. empty file). Going through 
the RFC, this is what I found:

One section says:

"If a valid byte-range-set includes at least one byte-range-spec with
a first-byte-pos that is less than the current length of the
representation, 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."

so since first-byte-pos can never be less than 0, it will always be 
unsatisfiable, and should return 416.

But the section on 416 says:

"The 416 (Range Not Satisfiable) status code indicates that none of
the ranges in the request's Range header field (Section 3.1) overlap
the current extent...
For byte ranges, failing to overlap the current extent means that the
first-byte-pos of all of the byte-range-spec values were greater than
the current length of the selected representation."

so a first-byte-pos of 0 is not greater than 0, and thus the 416 Not 
Satisfiable status does not apply here.

In addition to this contradiction, a 206 Partial Content response is not 
possible either since the required Content-Range can't specify an empty 
range (I think), plus, the response is not actually partial content.

For a suffix-byte-range-spec with a non-zero suffix length, it says:

"If the selected representation is shorter than the specified
suffix-length, the entire representation is used."

which will trivially include an empty representation if you're a 
mathematician, but in practice some implementations might try and 
calculate an actual numbered range and fall back into the same ambiguous 
416 code path (this is only a guess). And you still can't return a 206 
for it.

As for a suffix-byte-range spec with a 0 suffix length (-0)... I don't 
know what happens there.

Another consideration is the paragraph about allowing a client to limit 
the number of bytes requested without knowing the size of the selected 
representation. If a client always requests a range of e.g. 0-100000 for 
this stated purpose, it would likely expect to get normal 200 responses 
for anything under 100000 bytes (or possibly a 206?), and a truncated 
206 for anything larger, but not suddenly have to deal with a 416 and 
interpret it as a successful empty content response, or worse, perform 
another round-trip to the server without the Range to handle this case.

In short, the RFC's handling of empty resources with regards to ranges 
appears to be self-contradictory or not well-specified or unintuitive 
(I'm not sure which).

My humble suggestion would be to specify that servers should return an 
empty 200 response if the resource content is empty, which I think would 
minimize complexity on client and server. I may be wrong. But at the 
very least, the current wording should be clarified to mention this case 
explicitly and how it should be dealt with, since it's quite confusing 
currently.

Thanks for your time :-)

Amichai

---

From: Amos Jeffries <[email-masked]>
Date: Sat, 25 Jul 2015 06:02:11 +1200

> the RFC, this is what I found:

I agree.

> unsatisfiable, and should return 416.

For the record;

That is not Rothman' oppinion, but a SHOULD requirement from section 3.1
on returning 416 to all "unsatisfiable" ranges.

The quoted "first-byte-pos that is less than the current length of the
representation"

...  is from the end of section 2.1. After initial statements about how
"Byte offsets start at zero." and examples of how a client can request
range "bytes 0-0" and larger end position ranges all starting at 0.

206 definition says clearly its about transferring 1+ satifiable ranges.
Eliminating itself from relevance.

416 (as Rothman mentions below) says its about responding when all
requested first-byte-pos are *greater* than the available size.
Eliminating itself from relevance as well.

> In addition to this contradiction, a 206 Partial Content response is
> not possible either since the required Content-Range can't specify an
> empty range (I think), plus, the response is not actually partial
> content.
> 
> calculate an actual numbered range and fall back into the same
> ambiguous 416 code path (this is only a guess). And you still can't
> return a 206 for it.

Well that was the intent of that suffix form IIRC.

Requesting "bytes -N". To find out what the file size is and get the
last few bytes from it (if any) in the process. As it locating the
checksum bytes at the end for CDN applications. This is actually a
satisfiable range when applied to 0-sized files.

A response with unsatisfiable-range spec is then correct for 206 on a
0-sized file, "Content-Range: bytes */0"

A Content-Length:0 header would also be warranted to signal there is no
actual payload bytes present.

> 
> As for a suffix-byte-range spec with a 0 suffix length (-0)... I
> don't know what happens there.

Suffix is zero so its unsatisfiable and falls into the 416 path with the
unsatisfiable-range response header mentioned above.

Some other things need considering:

Theres Section 4.4:
"
Note: Because servers are free to ignore Range, many
implementations will simply respond with the entire selected
representation in a 200 (OK) response.
"

And RFC 7231 status:

If the file actually does not exist, as opposed to existing with 0 size,
then 404 is correct because there would not normally have been a 200
response anyway.

If it was not actually a file, but some processing logics producing no
output. Then 204 is appropriate, since it signals that processing was
enacted. Range is no more relevant here than on 404.

> another round-trip to the server without the Range to handle this case.

No round-trip is necessary. The "Content-Range: bytes */0" header
already contains explicit statement that the file is of 0-size which is
why the 416 happened (if at all).

> explicitly and how it should be dealt with, since it's quite confusing

It is noted at the end of section 4.4:
"
  Note: Because servers are free to ignore Range, many
      implementations will simply respond with the entire selected
      representation in a 200 (OK) response.
"

Athough 0-size is not called out. Because as mentioned above when the
right suffix-byte-range syntax is used the 206 does work. 204 or 404 may
also be applicable.

Amos

---

From: "Roy T. Fielding" <[email-masked]>
Date: Fri, 24 Jul 2015 14:01:30 -0700

> On Jul 23, 2015, at 12:16 PM, A. Rothman <[email-masked]> wrote:
> 
> Hi,
> 
> I'd like to suggest that RFC 7233 (or whatever will succeed it) should mention explicitly how a server should respond to a Range request when the requested resource has no content (e.g. empty file). Going through the RFC, this is what I found:

Sec 3.1: A server MAY ignore the Range header field.

> so since first-byte-pos can never be less than 0, it will always be unsatisfiable, and should return 416.

I agree that it would be better to say up front, somewhere, that Range
MUST be ignored if the current selected representation is zero length.
Likewise, we have already been asked to clarify that a 200 response is
sent whenever the entire representation is used.

However, Sec 3.1:
   If all of the preconditions are true, the server supports the Range
   header field for the target resource, and the specified range(s) are
   invalid or unsatisfiable, the server SHOULD send a 416 (Range Not
   Satisfiable) response.

and that requirement is a SHOULD to allow for these cases.  I believe that
the reason for sending 416 instead of 200 is so that a client can request
the next N bytes of a representation that it knows is append-only but
doesn't know if anything has been appended yet; this is an important use
case for things like large logfiles.  If 200 is preferred instead, the
If-Range header field can be sent.

> so a first-byte-pos of 0 is not greater than 0, and thus the 416 Not Satisfiable status does not apply here.

There are two bugs there. First, it should say "selected representation",
not selected resource.  Second, it means that the first-byte-pos of each
byte-range-spec value, if any, is greater than or equal to the current
length of the selected representation.

For example, "1-1" is one byte IFF content length is at least 2;
             "0-1" is one byte IFF content length is at least 1.
             "0-0" is one byte IFF content length is at least 1.

Thanks for noticing that error.  Did I mention that I hate this feature?
It should have just referred to the definitions of invalid and unsatisfiable.

> In addition to this contradiction, a 206 Partial Content response is not possible either since the required Content-Range can't specify an empty range (I think), plus, the response is not actually partial content.

There is no need to require that 206 not be sent when its semantics are not met.

> which will trivially include an empty representation if you're a mathematician, but in practice some implementations might try and calculate an actual numbered range and fall back into the same ambiguous 416 code path (this is only a guess). And you still can't return a 206 for it.

Right, that implies a 200 or 204 can be returned (assuming all other checks pass).
You don't need to be a mathematician: representation is a defined term that
includes zero-length bodies.

> As for a suffix-byte-range spec with a 0 suffix length (-0)... I don't know what happens there.

It is inherently unsatisfiable.

> Another consideration is the paragraph about allowing a client to limit the number of bytes requested without knowing the size of the selected representation. If a client always requests a range of e.g. 0-100000 for this stated purpose, it would likely expect to get normal 200 responses for anything under 100000 bytes (or possibly a 206?), and a truncated 206 for anything larger, but not suddenly have to deal with a 416 and interpret it as a successful empty content response, or worse, perform another round-trip to the server without the Range to handle this case.

See above.

> In short, the RFC's handling of empty resources with regards to ranges appears to be self-contradictory or not well-specified or unintuitive (I'm not sure which).
> 
> My humble suggestion would be to specify that servers should return an empty 200 response if the resource content is empty, which I think would minimize complexity on client and server. I may be wrong. But at the very least, the current wording should be clarified to mention this case explicitly and how it should be dealt with, since it's quite confusing currently.
> 
> Thanks for your time :-)
> 
> Amichai

The two bugs should be an errata.  We should probably explain why and when
the 416 code is used, but that's editorial.

Cheers,

....Roy