mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
net/http: make ServeContent support dates in If-Range headers
Fixes #8367 LGTM=adg R=adg CC=golang-codereviews https://golang.org/cl/116300044
This commit is contained in:
parent
20a5de9eb6
commit
f5037ee127
2 changed files with 39 additions and 8 deletions
|
|
@ -139,7 +139,7 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
|
||||||
if checkLastModified(w, r, modtime) {
|
if checkLastModified(w, r, modtime) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rangeReq, done := checkETag(w, r)
|
rangeReq, done := checkETag(w, r, modtime)
|
||||||
if done {
|
if done {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -275,11 +275,14 @@ func checkLastModified(w ResponseWriter, r *Request, modtime time.Time) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkETag implements If-None-Match and If-Range checks.
|
// checkETag implements If-None-Match and If-Range checks.
|
||||||
// The ETag must have been previously set in the ResponseWriter's headers.
|
//
|
||||||
|
// The ETag or modtime must have been previously set in the
|
||||||
|
// ResponseWriter's headers. The modtime is only compared at second
|
||||||
|
// granularity and may be the zero value to mean unknown.
|
||||||
//
|
//
|
||||||
// The return value is the effective request "Range" header to use and
|
// The return value is the effective request "Range" header to use and
|
||||||
// whether this request is now considered done.
|
// whether this request is now considered done.
|
||||||
func checkETag(w ResponseWriter, r *Request) (rangeReq string, done bool) {
|
func checkETag(w ResponseWriter, r *Request, modtime time.Time) (rangeReq string, done bool) {
|
||||||
etag := w.Header().get("Etag")
|
etag := w.Header().get("Etag")
|
||||||
rangeReq = r.Header.get("Range")
|
rangeReq = r.Header.get("Range")
|
||||||
|
|
||||||
|
|
@ -290,11 +293,17 @@ func checkETag(w ResponseWriter, r *Request) (rangeReq string, done bool) {
|
||||||
// We only support ETag versions.
|
// We only support ETag versions.
|
||||||
// The caller must have set the ETag on the response already.
|
// The caller must have set the ETag on the response already.
|
||||||
if ir := r.Header.get("If-Range"); ir != "" && ir != etag {
|
if ir := r.Header.get("If-Range"); ir != "" && ir != etag {
|
||||||
// TODO(bradfitz): handle If-Range requests with Last-Modified
|
// The If-Range value is typically the ETag value, but it may also be
|
||||||
// times instead of ETags? I'd rather not, at least for
|
// the modtime date. See golang.org/issue/8367.
|
||||||
// now. That seems like a bug/compromise in the RFC 2616, and
|
timeMatches := false
|
||||||
// I've never heard of anybody caring about that (yet).
|
if !modtime.IsZero() {
|
||||||
rangeReq = ""
|
if t, err := ParseTime(ir); err == nil && t.Unix() == modtime.Unix() {
|
||||||
|
timeMatches = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !timeMatches {
|
||||||
|
rangeReq = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if inm := r.Header.get("If-None-Match"); inm != "" {
|
if inm := r.Header.get("If-None-Match"); inm != "" {
|
||||||
|
|
|
||||||
|
|
@ -721,6 +721,28 @@ func TestServeContent(t *testing.T) {
|
||||||
wantStatus: 200,
|
wantStatus: 200,
|
||||||
wantContentType: "text/css; charset=utf-8",
|
wantContentType: "text/css; charset=utf-8",
|
||||||
},
|
},
|
||||||
|
"range_with_modtime": {
|
||||||
|
file: "testdata/style.css",
|
||||||
|
modtime: time.Date(2014, 6, 25, 17, 12, 18, 0 /* nanos */, time.UTC),
|
||||||
|
reqHeader: map[string]string{
|
||||||
|
"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",
|
||||||
|
},
|
||||||
|
"range_with_modtime_nanos": {
|
||||||
|
file: "testdata/style.css",
|
||||||
|
modtime: time.Date(2014, 6, 25, 17, 12, 18, 123 /* nanos */, time.UTC),
|
||||||
|
reqHeader: map[string]string{
|
||||||
|
"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",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for testName, tt := range tests {
|
for testName, tt := range tests {
|
||||||
var content io.ReadSeeker
|
var content io.ReadSeeker
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue