How does the Range
header work with Content Negotiation? Let me explain, but first let's all agree to the following: HTTP is a stateless protocol.
When an HTTP Server is able to send multiple representation of a single resource, content negotiation is used to figure which representation to send: The client might indicate its preference (i.e. English and GIFs) then the server would comply or -- in a scenario where it can't -- the server would choose, through some heuristic evaluation, which representation to send the client.
So far so good... but what happens when you throw Range
into the mix?
Imagine the following scenario:
John is in an airport in Paris and his browser sends an HTTP request. For some reason, his browser doesn't indicates any preferences in content type, language nor compression.
GET /uri HTTP/1.1 Host: example.com
Since it has very little to go by, the server, through some heuristics, decides to send the french representation of the URI (the IP is recognized as being from France.)
200 Okay Accept-Ranges: bytes Content: text/html Content-Language: fr ....data...
Mid-transfer, John stops the download to catch his flight. John resumes his download once he arrives in New York.
GET /uri HTTP/1.1 Host: example.com Range: 2000-3000
Again, with little information on the client's preference, the server this time decides to send the english representation of the URI (the IP is recognized as being from New York.)
By this point, the file is corrupt since part of it is in French and the other part is in English.
Conjecture:
Accept: text/html Accept-Language: fr
).
However, since nether RFC2616 nor RFC7233 state anything in regards to this (not even a recommendation), I believe HTTP clients
with this behaviour to be rare... but I have yet to test it.Notes:
GET /uri HTTP/1.1
Host: example.com
Accept: text/html; q=1.0, text/plain; q=0.8, */*; q=0.1
Accept-Language: en; q=1.0, */*; q=0.1
Range: 100-200
In the above, the range applies to which representation of the requested resource?!
Short answer: don't use Range request without If-Match: etag request header field.