-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathchain.go
More file actions
86 lines (68 loc) · 2.39 KB
/
chain.go
File metadata and controls
86 lines (68 loc) · 2.39 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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Package chain aids the composition of nested http.Handler instances.
package chain
import "net/http"
// Chain contains the current nested http.Handler data.
type Chain struct {
hs []func(http.Handler) http.Handler
}
// New receives one or more nested http.Handler instances, and returns a new
// Chain.
func New(handlers ...func(http.Handler) http.Handler) *Chain {
return &Chain{hs: handlers}
}
// appendHandlers differs from the append built-in in that it does not set the
// cap of the currently tracked handlers slice beyond it's required length.
// This ensures that additional appending produces expected results instead of
// allowing for the potential of collision/overwriting.
func appendHandlers(hs []func(http.Handler) http.Handler, ahs ...func(http.Handler) http.Handler) []func(http.Handler) http.Handler {
lcur := len(hs)
ltot := lcur + len(ahs)
if ltot > cap(hs) {
nhs := make([]func(http.Handler) http.Handler, ltot)
copy(nhs, hs)
hs = nhs
}
copy(hs[lcur:], ahs)
return hs
}
// Append receives one or more nested http.Handler instances, and appends the
// value to the returned Chain.
func (c *Chain) Append(handlers ...func(http.Handler) http.Handler) *Chain {
c = New(appendHandlers(c.hs, handlers...)...)
return c
}
// Merge receives one or more Chain instances, and returns a merged Chain.
func (c *Chain) Merge(chains ...*Chain) *Chain {
for k := range chains {
c = New(appendHandlers(c.hs, chains[k].hs...)...)
}
return c
}
// Copy receives one Chain instance, and copies it's handlers into the
// receiver's handlers slice.
func (c *Chain) Copy(chain *Chain) {
c.hs = make([]func(http.Handler) http.Handler, len(chain.hs))
for k := range chain.hs {
c.hs[k] = chain.hs[k]
}
}
// End receives an http.Handler, and returns an http.Handler comprised of all
// nested http.Handler data where the received http.Handler is the endpoint.
func (c *Chain) End(handler http.Handler) http.Handler {
if handler == nil {
handler = http.HandlerFunc(emptyHandler)
}
for i := len(c.hs) - 1; i >= 0; i-- {
handler = c.hs[i](handler)
}
return handler
}
// EndFn receives an instance of http.HandlerFunc, then passes it to End to
// return an http.Handler.
func (c *Chain) EndFn(handlerFunc http.HandlerFunc) http.Handler {
if handlerFunc == nil {
handlerFunc = http.HandlerFunc(emptyHandler)
}
return c.End(handlerFunc)
}
func emptyHandler(w http.ResponseWriter, r *http.Request) {}