From: Dmitri Shuralyov Date: Thu, 21 Sep 2017 05:53:13 +0000 (-0400) Subject: net/http: set Content-Type header for HEAD as well X-Git-Tag: go1.10beta1~469 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=2ff75551030c7e54bd1cec3e88805d4ea3232276;p=gostls13.git net/http: set Content-Type header for HEAD as well In CL 50510, the Content-Type header started to be set in Redirect when request method is GET. (Prior to that, it wasn't set at all, which is what said CL was fixing.) However, according to HTTP specification, the expected response for a HEAD request is identical to that of a GET request, but without the response body. This CL updates the behavior to set the Content-Type header for HEAD method in addition to GET. This actually allows a simpler implementation than before. This change largely reverts CL 50510, and applies the simpler implementation. Add a test for Content-Type header and body for GET, HEAD requests. Updates CL 50510. Change-Id: If33ea3f4bbc5246bb5dc751458004828cfe681b9 Reviewed-on: https://go-review.googlesource.com/65190 Run-TryBot: Dmitri Shuralyov TryBot-Result: Gobot Gobot Reviewed-by: Emmanuel Odeke Reviewed-by: Tom Bergan --- diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index bbc6ed5f44..508d8b53f1 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -2506,6 +2506,37 @@ func TestRedirect(t *testing.T) { } } +// Test that Content-Type header is set for GET and HEAD requests. +func TestRedirectContentTypeAndBody(t *testing.T) { + var tests = []struct { + method string + wantCT string + wantBody string + }{ + {MethodGet, "text/html; charset=utf-8", "Found.\n\n"}, + {MethodHead, "text/html; charset=utf-8", ""}, + {MethodPost, "", ""}, + {MethodDelete, "", ""}, + {"foo", "", ""}, + } + for _, tt := range tests { + req := httptest.NewRequest(tt.method, "http://example.com/qux/", nil) + rec := httptest.NewRecorder() + Redirect(rec, req, "/foo", 302) + if got, want := rec.Header().Get("Content-Type"), tt.wantCT; got != want { + t.Errorf("Redirect(%q) generated Content-Type header %q; want %q", tt.method, got, want) + } + resp := rec.Result() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + if got, want := string(body), tt.wantBody; got != want { + t.Errorf("Redirect(%q) generated Body %q; want %q", tt.method, got, want) + } + } +} + // TestZeroLengthPostAndResponse exercises an optimization done by the Transport: // when there is no body (either because the method doesn't permit a body, or an // explicit Content-Length of zero is present), then the transport can re-use the diff --git a/src/net/http/server.go b/src/net/http/server.go index cfc6654ff4..91f481ed50 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -2016,17 +2016,16 @@ func Redirect(w ResponseWriter, r *Request, url string, code int) { } } - // RFC 2616 recommends that a short note "SHOULD" be included in the - // response because older user agents may not understand 301/307. - // Shouldn't send the response for POST or HEAD; that leaves GET. - writeNote := r.Method == "GET" - w.Header().Set("Location", hexEscapeNonASCII(url)) - if writeNote { + if r.Method == "GET" || r.Method == "HEAD" { w.Header().Set("Content-Type", "text/html; charset=utf-8") } w.WriteHeader(code) - if writeNote { + + // RFC 2616 recommends that a short note "SHOULD" be included in the + // response because older user agents may not understand 301/307. + // Shouldn't send the response for POST or HEAD; that leaves GET. + if r.Method == "GET" { note := "" + statusText[code] + ".\n" fmt.Fprintln(w, note) }