]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: redirect handlers from mux.Handler() shouldn't clear the query string
authorShenghou Ma <minux.ma@gmail.com>
Thu, 29 Aug 2013 20:55:12 +0000 (13:55 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 29 Aug 2013 20:55:12 +0000 (13:55 -0700)
R=bradfitz, alberto.garcia.hierro, rsc, adg
CC=golang-dev
https://golang.org/cl/7099045

src/pkg/net/http/serve_test.go
src/pkg/net/http/server.go

index 5d08d2facab75f7cb62d95cf8cabafd643d98284..c7c842b2fdb7e4b759c6cf272ea4bc319c4f42eb 100644 (file)
@@ -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"}
index 3c327839cbb12a8bcfa7950c1045b3217ce4d3c2..0c1a1408678b3b8a1d9088f6dcfcbd26e04cd7c8 100644 (file)
@@ -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
                }
        }