internal/httpd/trailingslash_test.go

a32f7f2001c1c0bf38ba8c3360e6bc7ca3982fee
gitbay/internal/httpd/trailingslash_test.go history · blame · raw

47 lines · 1589 bytes

 1package httpd
 2
 3import (
 4	"net/http"
 5	"net/http/httptest"
 6	"strings"
 7	"testing"
 8)
 9
10// A path that only misses because of a trailing slash redirects to the
11// path without it, query intact; one that misses either way is 404, and
12// a POST is never redirected (#233).
13func TestTrailingSlashRedirects(t *testing.T) {
14	h := plainServer().Handler()
15	for from, to := range map[string]string{
16		"/cmc/":                   "/cmc",
17		"/cmc/ccleberg/":          "/cmc/ccleberg",
18		"/cmc/-/snippets/":        "/cmc/-/snippets",
19		"/krz/gitbay/mrs/12/":     "/krz/gitbay/mrs/12",
20		"/krz/gitbay/issues/?q=x": "/krz/gitbay/issues?q=x",
21	} {
22		w := get(t, h, from, nil)
23		if w.Code != http.StatusMovedPermanently || w.Header().Get("Location") != to {
24			t.Errorf("%s: %d %q, want 301 %q", from, w.Code, w.Header().Get("Location"), to)
25		}
26	}
27	for _, p := range []string{"/", "/krz/gitbay/nothing/"} {
28		if w := get(t, h, p, nil); p != "/" && w.Code != 404 {
29			t.Errorf("%s: status %d, want 404", p, w.Code)
30		}
31	}
32	// A Location must not leave the site: the mux cleans a leading //
33	// before the fallback runs, and a backslash is escaped (#153).
34	for _, p := range []string{"//evil.example/", "/\\evil.example/"} {
35		w := get(t, h, p, nil)
36		if loc := w.Header().Get("Location"); strings.HasPrefix(loc, "//") || strings.Contains(loc, "\\") {
37			t.Errorf("%s: Location %q leaves the site", p, loc)
38		}
39	}
40	r := httptest.NewRequest("POST", "/cmc/", nil)
41	r.Host = "forge.test"
42	w := httptest.NewRecorder()
43	h.ServeHTTP(w, r)
44	if w.Code != 404 {
45		t.Errorf("POST /cmc/: status %d, want 404", w.Code)
46	}
47}