}
}
+// Test that we don't attempt trailing-slash redirect on a path that already has
+// a trailing slash.
+// See issue #65624.
+func TestMuxNoSlashRedirectWithTrailingSlash(t *testing.T) {
+ mux := NewServeMux()
+ mux.HandleFunc("/{x}/", func(w ResponseWriter, r *Request) {
+ fmt.Fprintln(w, "ok")
+ })
+ w := httptest.NewRecorder()
+ req, _ := NewRequest("GET", "/", nil)
+ mux.ServeHTTP(w, req)
+ if g, w := w.Code, 404; g != w {
+ t.Errorf("got %d, want %d", g, w)
+ }
+}
+
func TestShouldRedirectConcurrency(t *testing.T) { run(t, testShouldRedirectConcurrency) }
func testShouldRedirectConcurrency(t *testing.T, mode testMode) {
mux := NewServeMux()
n, matches := mux.tree.match(host, method, path)
// If we have an exact match, or we were asked not to try trailing-slash redirection,
- // then we're done.
- if !exactMatch(n, path) && u != nil {
+ // or the URL already has a trailing slash, then we're done.
+ if !exactMatch(n, path) && u != nil && !strings.HasSuffix(path, "/") {
// If there is an exact match with a trailing slash, then redirect.
path += "/"
n2, _ := mux.tree.match(host, method, path)
t.Run("1.21", func(t *testing.T) { run(t, true) })
}
+func TestCleanPath(t *testing.T) {
+ for _, test := range []struct {
+ in, want string
+ }{
+ {"//", "/"},
+ {"/x", "/x"},
+ {"//x", "/x"},
+ {"x//", "/x/"},
+ {"a//b/////c", "/a/b/c"},
+ {"/foo/../bar/./..//baz", "/baz"},
+ } {
+ got := cleanPath(test.in)
+ if got != test.want {
+ t.Errorf("%s: got %q, want %q", test.in, got, test.want)
+ }
+ }
+}
+
func BenchmarkServerMatch(b *testing.B) {
fn := func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "OK")