Commit dc4b9cff authored by Sam Whited's avatar Sam Whited Committed by Brad Fitzpatrick

net/http: don't write redirect body if content-type is set

Fixes #25166

Change-Id: Id1fe18899579365519ac08ebedf74cd23c0fbd9f
Reviewed-on: https://go-review.googlesource.com/110296
Run-TryBot: Sam Whited <sam@samwhited.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 6f7fa68b
...@@ -2589,20 +2589,29 @@ func TestRedirect(t *testing.T) { ...@@ -2589,20 +2589,29 @@ func TestRedirect(t *testing.T) {
// Test that Content-Type header is set for GET and HEAD requests. // Test that Content-Type header is set for GET and HEAD requests.
func TestRedirectContentTypeAndBody(t *testing.T) { func TestRedirectContentTypeAndBody(t *testing.T) {
var unsetCT = []string{"sentinalValNoCT"}
var tests = []struct { var tests = []struct {
initCT []string
method string method string
wantCT string wantCT string
wantBody string wantBody string
}{ }{
{MethodGet, "text/html; charset=utf-8", "<a href=\"/foo\">Found</a>.\n\n"}, {unsetCT, MethodGet, "text/html; charset=utf-8", "<a href=\"/foo\">Found</a>.\n\n"},
{MethodHead, "text/html; charset=utf-8", ""}, {unsetCT, MethodHead, "text/html; charset=utf-8", ""},
{MethodPost, "", ""}, {unsetCT, MethodPost, "", ""},
{MethodDelete, "", ""}, {unsetCT, MethodDelete, "", ""},
{"foo", "", ""}, {unsetCT, "foo", "", ""},
{[]string{"application/test"}, MethodGet, "application/test", ""},
{[]string{}, MethodGet, "", ""},
{nil, MethodGet, "", ""},
} }
for _, tt := range tests { for _, tt := range tests {
req := httptest.NewRequest(tt.method, "http://example.com/qux/", nil) req := httptest.NewRequest(tt.method, "http://example.com/qux/", nil)
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
if len(tt.initCT) != 1 || &tt.initCT[0] != &unsetCT[0] {
rec.Header()["Content-Type"] = tt.initCT
}
Redirect(rec, req, "/foo", 302) Redirect(rec, req, "/foo", 302)
if got, want := rec.Header().Get("Content-Type"), tt.wantCT; got != want { 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) t.Errorf("Redirect(%q) generated Content-Type header %q; want %q", tt.method, got, want)
......
...@@ -2003,6 +2003,9 @@ func StripPrefix(prefix string, h Handler) Handler { ...@@ -2003,6 +2003,9 @@ func StripPrefix(prefix string, h Handler) Handler {
// //
// The provided code should be in the 3xx range and is usually // The provided code should be in the 3xx range and is usually
// StatusMovedPermanently, StatusFound or StatusSeeOther. // StatusMovedPermanently, StatusFound or StatusSeeOther.
// If Content-Type has not been set Redirect sets the header to
// "text/html; charset=utf-8" and writes a small HTML body.
// Setting the Content-Type header to nil also prevents writing the body.
func Redirect(w ResponseWriter, r *Request, url string, code int) { func Redirect(w ResponseWriter, r *Request, url string, code int) {
// parseURL is just url.Parse (url is shadowed for godoc). // parseURL is just url.Parse (url is shadowed for godoc).
if u, err := parseURL(url); err == nil { if u, err := parseURL(url); err == nil {
...@@ -2039,9 +2042,14 @@ func Redirect(w ResponseWriter, r *Request, url string, code int) { ...@@ -2039,9 +2042,14 @@ func Redirect(w ResponseWriter, r *Request, url string, code int) {
} }
} }
w.Header().Set("Location", hexEscapeNonASCII(url)) h := w.Header()
h.Set("Location", hexEscapeNonASCII(url))
if _, ok := h["Content-Type"]; ok {
return
}
if r.Method == "GET" || r.Method == "HEAD" { if r.Method == "GET" || r.Method == "HEAD" {
w.Header().Set("Content-Type", "text/html; charset=utf-8") h.Set("Content-Type", "text/html; charset=utf-8")
} }
w.WriteHeader(code) w.WriteHeader(code)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment