net/http: send Content-Range if no byte range overlaps

RFC 7233, section 4.4 says:
>>>
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.  When this status code is
generated in response to a byte-range request, the sender SHOULD generate a
Content-Range header field specifying the current length of the selected
representation
<<<

Thus, we should send the Content-Range only if none of the ranges
overlap.

Fixes #15798.

Change-Id: Ic9a3e1b3a8730398b4bdff877a8f2fd2e30149e3
Reviewed-on: https://go-review.googlesource.com/24212
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Sina Siadat 2016-06-17 21:02:59 +04:30 committed by Brad Fitzpatrick
parent 0bc94a8864
commit aa9b3d7014
3 changed files with 46 additions and 10 deletions

View file

@ -765,6 +765,7 @@ func TestServeContent(t *testing.T) {
reqHeader map[string]string
wantLastMod string
wantContentType string
wantContentRange string
wantStatus int
}
htmlModTime := mustStat(t, "testdata/index.html").ModTime()
@ -820,8 +821,19 @@ func TestServeContent(t *testing.T) {
reqHeader: map[string]string{
"Range": "bytes=0-4",
},
wantStatus: StatusPartialContent,
wantContentType: "text/css; charset=utf-8",
wantStatus: StatusPartialContent,
wantContentType: "text/css; charset=utf-8",
wantContentRange: "bytes 0-4/8",
},
"range_no_overlap": {
file: "testdata/style.css",
serveETag: `"A"`,
reqHeader: map[string]string{
"Range": "bytes=10-20",
},
wantStatus: StatusRequestedRangeNotSatisfiable,
wantContentType: "text/plain; charset=utf-8",
wantContentRange: "bytes */8",
},
// An If-Range resource for entity "A", but entity "B" is now current.
// The Range request should be ignored.
@ -842,9 +854,10 @@ func TestServeContent(t *testing.T) {
"Range": "bytes=0-4",
"If-Range": "Wed, 25 Jun 2014 17:12:18 GMT",
},
wantStatus: StatusPartialContent,
wantContentType: "text/css; charset=utf-8",
wantLastMod: "Wed, 25 Jun 2014 17:12:18 GMT",
wantStatus: StatusPartialContent,
wantContentType: "text/css; charset=utf-8",
wantContentRange: "bytes 0-4/8",
wantLastMod: "Wed, 25 Jun 2014 17:12:18 GMT",
},
"range_with_modtime_nanos": {
file: "testdata/style.css",
@ -853,9 +866,10 @@ func TestServeContent(t *testing.T) {
"Range": "bytes=0-4",
"If-Range": "Wed, 25 Jun 2014 17:12:18 GMT",
},
wantStatus: StatusPartialContent,
wantContentType: "text/css; charset=utf-8",
wantLastMod: "Wed, 25 Jun 2014 17:12:18 GMT",
wantStatus: StatusPartialContent,
wantContentType: "text/css; charset=utf-8",
wantContentRange: "bytes 0-4/8",
wantLastMod: "Wed, 25 Jun 2014 17:12:18 GMT",
},
"unix_zero_modtime": {
content: strings.NewReader("<html>foo"),
@ -903,6 +917,9 @@ func TestServeContent(t *testing.T) {
if g, e := res.Header.Get("Content-Type"), tt.wantContentType; g != e {
t.Errorf("test %q: content-type = %q, want %q", testName, g, e)
}
if g, e := res.Header.Get("Content-Range"), tt.wantContentRange; g != e {
t.Errorf("test %q: content-range = %q, want %q", testName, g, e)
}
if g, e := res.Header.Get("Last-Modified"), tt.wantLastMod; g != e {
t.Errorf("test %q: last-modified = %q, want %q", testName, g, e)
}