fix(http/file_server): fix Range
header handling
#3354
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
close #3353
Current file servers' handling of the Range header is different from typical server's handling.
After verifying with google cloud storage, cloudflare, AWS cloudfront, githubusercontent.com, express lib, etc., it seems that Range requests are handled roughly in the manner shown in the table below.
These differences are causing problems like denoland/deploy_feedback#377.
In this PR, I rewrote the handling of the Range header to behave as per spec and behave the same as a typical server.
When requesting a file with content-length of 100:
(e.g. cloud storage, cloudfront, github...)
range: bytes=0-10
🟡206 Partial Content
(
content-range: bytes 0-10/100
)🟡206 Partial Content
(
content-range: bytes 0-10/100
)range: bytes=90-
🟡206 Partial Content
(
content-range: bytes 90-99/100
)🟡206 Partial Content
(
content-range: bytes 90-99/100
)range: bytes=-10
(means the last 10 bytes)🔴416 Range Not Satisfiable
(no
content-range
header: wrong)🟡206 Partial Content
(
content-range: bytes 90-99/100
)range: bytes=90-110
🔴416 Range Not Satisfiable
(
content-range: bytes 90-110/100
: wrong)🟡206 Partial Content
(
content-range: bytes 90-99/100
, The range is clamped)range: bytes=-110
(means the last 110 bytes)🔴416 Range Not Satisfiable
(no
content-range
header: wrong)🟡206 Partial Content
(
content-range: bytes 0-99/100
, The range is clamped)range: bytes=110-120
(out of range)🔴416 Range Not Satisfiable
(
content-range: bytes 110-120/100
: wrong)🔴416 Range Not Satisfiable
(
content-range: bytes */100
)range: bytes=110-
(out of range)🔴416 Range Not Satisfiable
(
content-range: bytes 110-99/100
: wrong)🔴416 Range Not Satisfiable
(
content-range: bytes */100
)range: bytes=20-10
(invalid)🔴416 Range Not Satisfiable
(
content-range: bytes 20-10/100
: wrong)🔴416 Range Not Satisfiable
(
content-range: bytes */100
)range: bytes=foobar
(invalid)🔴416 Range Not Satisfiable
(no
content-range
header: wrong)🟢200 OK
range: bytes=0-10,20-30
🟡206 Partial Content
(
content-range: bytes 0-10/100
, Only the first part is accepted)🟢200 OK
Note:
content-range: bytes */100
header is required when returning416 Range Not Satisfiable
response.A Range request to an empty file should always return416 Range Not Satisfiable
.It seems reasonable to return a 200 OK for a Range request to an empty file.
Requesting multiple Ranges like
range: bytes=0-10,20-30
is allowed by the spec, but as far as I know, few servers supports it.Sorry for the large git diff! Thank you for your review every time.