From 6a7c4d69cb72f857b21c36ef077de0b97d9dbd50 Mon Sep 17 00:00:00 2001 From: Joe Kyo Date: Wed, 9 Aug 2017 03:26:45 +0100 Subject: [PATCH] net/http: check If-Range header when request method is HEAD When If-Range does not match and the requested resource is available, server should return a "200 OK" response to client. Currently server returns "200 OK" when the request method is GET, but "206 Partial Content" when method is HEAD. This change fixed this inconsistency. Change-Id: I5ad979919f4f089baba54a4445b70ca38471a906 Reviewed-on: https://go-review.googlesource.com/54110 Run-TryBot: Tom Bergan TryBot-Result: Gobot Gobot Reviewed-by: Tom Bergan --- src/net/http/fs.go | 2 +- src/net/http/fs_test.go | 81 +++++++++++++++++++++++++---------------- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/net/http/fs.go b/src/net/http/fs.go index 5819334b5f..cda08b4a5b 100644 --- a/src/net/http/fs.go +++ b/src/net/http/fs.go @@ -445,7 +445,7 @@ func checkIfModifiedSince(r *Request, modtime time.Time) condResult { } func checkIfRange(w ResponseWriter, r *Request, modtime time.Time) condResult { - if r.Method != "GET" { + if r.Method != "GET" && r.Method != "HEAD" { return condNone } ir := r.Header.get("If-Range") diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go index f1037c4b5c..798cb30b29 100644 --- a/src/net/http/fs_test.go +++ b/src/net/http/fs_test.go @@ -895,6 +895,17 @@ func TestServeContent(t *testing.T) { wantContentRange: "bytes 0-4/8", wantLastMod: "Wed, 25 Jun 2014 17:12:18 GMT", }, + "range_with_modtime_mismatch": { + 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:19 GMT", + }, + wantStatus: StatusOK, + 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), @@ -982,40 +993,46 @@ func TestServeContent(t *testing.T) { } else { content = tt.content } + for _, method := range []string{"GET", "HEAD"} { + //restore content in case it is consumed by previous method + if content, ok := content.(*strings.Reader); ok { + content.Seek(io.SeekStart, 0) + } - servec <- serveParam{ - name: filepath.Base(tt.file), - content: content, - modtime: tt.modtime, - etag: tt.serveETag, - contentType: tt.serveContentType, - } - req, err := NewRequest("GET", ts.URL, nil) - if err != nil { - t.Fatal(err) - } - for k, v := range tt.reqHeader { - req.Header.Set(k, v) - } + servec <- serveParam{ + name: filepath.Base(tt.file), + content: content, + modtime: tt.modtime, + etag: tt.serveETag, + contentType: tt.serveContentType, + } + req, err := NewRequest(method, ts.URL, nil) + if err != nil { + t.Fatal(err) + } + for k, v := range tt.reqHeader { + req.Header.Set(k, v) + } - c := ts.Client() - res, err := c.Do(req) - if err != nil { - t.Fatal(err) - } - io.Copy(ioutil.Discard, res.Body) - res.Body.Close() - if res.StatusCode != tt.wantStatus { - t.Errorf("test %q: status = %d; want %d", testName, res.StatusCode, tt.wantStatus) - } - 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) + c := ts.Client() + res, err := c.Do(req) + if err != nil { + t.Fatal(err) + } + io.Copy(ioutil.Discard, res.Body) + res.Body.Close() + if res.StatusCode != tt.wantStatus { + t.Errorf("test %q using %q: got status = %d; want %d", testName, method, res.StatusCode, tt.wantStatus) + } + if g, e := res.Header.Get("Content-Type"), tt.wantContentType; g != e { + t.Errorf("test %q using %q: got content-type = %q, want %q", testName, method, g, e) + } + if g, e := res.Header.Get("Content-Range"), tt.wantContentRange; g != e { + t.Errorf("test %q using %q: got content-range = %q, want %q", testName, method, g, e) + } + if g, e := res.Header.Get("Last-Modified"), tt.wantLastMod; g != e { + t.Errorf("test %q using %q: got last-modified = %q, want %q", testName, method, g, e) + } } } } -- 2.48.1