From: Shenghou Ma Date: Thu, 29 Aug 2013 20:55:12 +0000 (-0700) Subject: net/http: redirect handlers from mux.Handler() shouldn't clear the query string X-Git-Tag: go1.2rc2~386 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=716a409b9044850d0edf11318ec0eca63de57a93;p=gostls13.git net/http: redirect handlers from mux.Handler() shouldn't clear the query string R=bradfitz, alberto.garcia.hierro, rsc, adg CC=golang-dev https://golang.org/cl/7099045 --- diff --git a/src/pkg/net/http/serve_test.go b/src/pkg/net/http/serve_test.go index 5d08d2faca..c7c842b2fd 100644 --- a/src/pkg/net/http/serve_test.go +++ b/src/pkg/net/http/serve_test.go @@ -277,6 +277,7 @@ var serveMuxRegister = []struct { {"/search", serve(201)}, {"codesearch.google.com/search", serve(202)}, {"codesearch.google.com/", serve(203)}, + {"example.com/", HandlerFunc(checkQueryStringHandler)}, } // serve returns a handler that sends a response with the given code. @@ -286,6 +287,21 @@ func serve(code int) HandlerFunc { } } +// checkQueryStringHandler checks if r.URL.RawQuery has the same value +// as the URL excluding the scheme and the query string and sends 200 +// response code if it is, 500 otherwise. +func checkQueryStringHandler(w ResponseWriter, r *Request) { + u := *r.URL + u.Scheme = "http" + u.Host = r.Host + u.RawQuery = "" + if "http://"+r.URL.RawQuery == u.String() { + w.WriteHeader(200) + } else { + w.WriteHeader(500) + } +} + var serveMuxTests = []struct { method string host string @@ -344,6 +360,61 @@ func TestServeMuxHandler(t *testing.T) { } } +var serveMuxTests2 = []struct { + method string + host string + url string + code int + redirOk bool +}{ + {"GET", "google.com", "/", 404, false}, + {"GET", "example.com", "/test/?example.com/test/", 200, false}, + {"GET", "example.com", "test/?example.com/test/", 200, true}, +} + +// TestServeMuxHandlerRedirects tests that automatic redirects generated by +// mux.Handler() shouldn't clear the request's query string. +func TestServeMuxHandlerRedirects(t *testing.T) { + mux := NewServeMux() + for _, e := range serveMuxRegister { + mux.Handle(e.pattern, e.h) + } + + for _, tt := range serveMuxTests2 { + tries := 1 + turl := tt.url + for tries > 0 { + u, e := url.Parse(turl) + if e != nil { + t.Fatal(e) + } + r := &Request{ + Method: tt.method, + Host: tt.host, + URL: u, + } + h, _ := mux.Handler(r) + rr := httptest.NewRecorder() + h.ServeHTTP(rr, r) + if rr.Code != 301 { + if rr.Code != tt.code { + t.Errorf("%s %s %s = %d, want %d", tt.method, tt.host, tt.url, rr.Code, tt.code) + } + break + } + if !tt.redirOk { + t.Errorf("%s %s %s, unexpected redirect", tt.method, tt.host, tt.url) + break + } + turl = rr.HeaderMap.Get("Location") + tries-- + } + if tries < 0 { + t.Errorf("%s %s %s, too many redirects", tt.method, tt.host, tt.url) + } + } +} + // Tests for http://code.google.com/p/go/issues/detail?id=900 func TestMuxRedirectLeadingSlashes(t *testing.T) { paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"} diff --git a/src/pkg/net/http/server.go b/src/pkg/net/http/server.go index 3c327839cb..0c1a140867 100644 --- a/src/pkg/net/http/server.go +++ b/src/pkg/net/http/server.go @@ -1448,7 +1448,9 @@ func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) { if r.Method != "CONNECT" { if p := cleanPath(r.URL.Path); p != r.URL.Path { _, pattern = mux.handler(r.Host, p) - return RedirectHandler(p, StatusMovedPermanently), pattern + url := *r.URL + url.Path = p + return RedirectHandler(url.String(), StatusMovedPermanently), pattern } }