-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathheader_validation_middleware.go
More file actions
45 lines (41 loc) · 1.55 KB
/
Copy pathheader_validation_middleware.go
File metadata and controls
45 lines (41 loc) · 1.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package routeit
import "github.com/sktylr/routeit/internal/trie"
// This middleware is the second (or third, if request ID's are assigned to
// each incoming request) piece of middleware run on all server
// instances. It will block requests that illegally contain repeated header
// values. Some of the headers that are blocked are blocked for security
// reasons (e.g. multiple "Authorization" headers poses a security risk), while
// others are blocked due to being nonsensical (e.g. multiple "Content-Type"
// headers makes no sense and makes parsing unreliable). If the middleware
// detects multiple header values for any of the default or additionally
// supplied headers, the request will be blocked. For security purposes, the
// request is blocked on the first offender and only includes information about
// that offender.
func headerValidationMiddleware(disallow []string) Middleware {
trie := trie.NewRuneTrie()
defaults := []string{
"Host",
"Content-Length",
"Content-Type",
"User-Agent",
"Authorization",
"Origin",
"Cookie",
"Referer",
"Range",
"Expect",
}
// We use a trie here to benefit from not having repeated elements and
// case-insensitive insertion.
for _, d := range append(defaults, disallow...) {
trie.Insert(d)
}
return func(c Chain, rw *ResponseWriter, req *Request) error {
for header := range trie.Traverse() {
if vals, found := req.Headers().All(header); found && len(vals) > 1 {
return ErrBadRequest().WithMessagef("Header %#q cannot appear more than once", header)
}
}
return c.Proceed(rw, req)
}
}