carlos / movement Public

Clone
git clone https://amadan.net/carlos/movement

Plain git — no account needed to clone.

Download

Download this file

1package movementtest
2
3import (
4 "net/http"
5 "net/http/httptest"
6 "testing"
7)
8
9// Every public page must answer HEAD, not 405.
10//
11// chi routes HEAD only where a handler is registered for it, so a router built
12// from r.Get alone refuses every HEAD request — and HEAD is what uptime
13// checks, link unfurlers and a fair amount of crawler traffic send before
14// anything else. This was found with curl -I against the deployed host after
15// the first deploy, which is later than it should have been.
16func TestPublicPagesAnswerHead(t *testing.T) {
17 h := newApp(t)
18
19 for _, path := range []string{"/", "/no-ai", "/uneasy", "/all-in"} {
20 req := httptest.NewRequest(http.MethodHead, path, nil)
21 rec := httptest.NewRecorder()
22 h.ServeHTTP(rec, req)
23
24 if rec.Code != http.StatusOK {
25 t.Errorf("HEAD %s: status %d, want 200", path, rec.Code)
26 }
27 }
28}
29
30// HEAD must not become a way to make the app do work a GET would refuse.
31// csrf.Protect only guards state-changing methods, so the check that matters
32// is that the signup endpoint still refuses anything but POST.
33func TestSignupIgnoresHead(t *testing.T) {
34 h := newApp(t)
35
36 req := httptest.NewRequest(http.MethodHead, "/signup", nil)
37 rec := httptest.NewRecorder()
38 h.ServeHTTP(rec, req)
39
40 if rec.Code == http.StatusOK {
41 t.Error("HEAD /signup answered 200; only POST should reach the handler")
42 }
43 if got := countNonces(t, h); got != 0 {
44 t.Errorf("a HEAD request spent %d nonces", got)
45 }
46}
47