internal/httpd/trailingslash_test.go
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}