1
0
mirror of https://github.com/golang/go synced 2024-11-25 18:07:57 -07:00

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
This commit is contained in:
Shenghou Ma 2013-08-29 13:55:12 -07:00 committed by Brad Fitzpatrick
parent c51152f438
commit 716a409b90
2 changed files with 74 additions and 1 deletions

View File

@ -277,6 +277,7 @@ var serveMuxRegister = []struct {
{"/search", serve(201)}, {"/search", serve(201)},
{"codesearch.google.com/search", serve(202)}, {"codesearch.google.com/search", serve(202)},
{"codesearch.google.com/", serve(203)}, {"codesearch.google.com/", serve(203)},
{"example.com/", HandlerFunc(checkQueryStringHandler)},
} }
// serve returns a handler that sends a response with the given code. // 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 { var serveMuxTests = []struct {
method string method string
host 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 // Tests for http://code.google.com/p/go/issues/detail?id=900
func TestMuxRedirectLeadingSlashes(t *testing.T) { func TestMuxRedirectLeadingSlashes(t *testing.T) {
paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"} paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"}

View File

@ -1448,7 +1448,9 @@ func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
if r.Method != "CONNECT" { if r.Method != "CONNECT" {
if p := cleanPath(r.URL.Path); p != r.URL.Path { if p := cleanPath(r.URL.Path); p != r.URL.Path {
_, pattern = mux.handler(r.Host, p) _, pattern = mux.handler(r.Host, p)
return RedirectHandler(p, StatusMovedPermanently), pattern url := *r.URL
url.Path = p
return RedirectHandler(url.String(), StatusMovedPermanently), pattern
} }
} }