coverage~bigbes/sr-ht-ecoreb36a9272pages/form.go

Coverage
100.0% 6/6 statements
Δ
+0.0
Blob
e8ab156
Uncovered nothing — every instrumented line ran
1 package pages
2
3 import (
4 "errors"
5 "fmt"
6 "net/http"
7 "net/url"
8 )
9
10 // DefaultMaxFormBytes bounds a urlencoded body. net/http's own ceiling for one
11 // is 10 MiB per request, which is three orders of magnitude more than any form
12 // on this instance sends and enough to be worth refusing on a page anyone can
13 // reach without logging in.
14 const DefaultMaxFormBytes = 1 << 16
15
16 // ErrInvalidForm is returned when the body could not be read as a form: it was
17 // malformed, or it exceeded the limit. A service maps this to 400.
18 var ErrInvalidForm = errors.New("pages: the form could not be read")
19
20 // FormValues reads a urlencoded body, bounded at max (DefaultMaxFormBytes when
21 // max <= 0), and returns the body's values.
22 //
23 // It returns r.PostForm and never r.Form, and that is the whole reason this
24 // three-line function is shared rather than copied. r.Form merges the query
25 // string into the body's values, so a mutation could be driven entirely from a
26 // URL somebody was linked to — and that request is precisely the one the
27 // same-origin guard sees nothing wrong with, because it really did come from
28 // our own page. A form posts its fields in its body; anything in the query
29 // string of such a POST is not that form.
30 //
31 // The difference between the safe version and the hole is one character in a
32 // field name, in a function every service with a form writes for itself, and
33 // nothing at review time makes its absence visible. That is what makes it
34 // belong beside csrf rather than in each service.
35 4 func FormValues(w http.ResponseWriter, r *http.Request, max int64) (url.Values, error) {
36 4 if max <= 0 {
37 2 max = DefaultMaxFormBytes
38 2 }
39 4 r.Body = http.MaxBytesReader(w, r.Body, max)
40 4 if err := r.ParseForm(); err != nil {
41 2 return nil, fmt.Errorf("%w (%v)", ErrInvalidForm, err)
42 2 }
43 2 return r.PostForm, nil
44 }