-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmiddleware.go
102 lines (80 loc) · 2.51 KB
/
middleware.go
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package middleware
type Handler interface {
Call(env map[string]interface{})
}
type HandlerFunc func(env map[string]interface{})
func (h HandlerFunc) Call(env map[string]interface{}) {
h(env)
}
// A handler that responds to a arbitrary request
// Call should write state changes to the map
type MiddlewareHandler interface {
Call(env map[string]interface{}, next HandlerFunc)
}
// The MiddlewareHandlerFunc type is an adapter to allow the use of ordinary
// functions as MiddlewareHandler handlers. If f is a function with the
// appropriate signature, MiddlewareHandlerFunc(f) is a MiddlewareHandler that calls f.
type MiddlewareHandlerFunc func(env map[string]interface{}, next HandlerFunc)
func (f MiddlewareHandlerFunc) Call(env map[string]interface{}, next HandlerFunc) {
f(env, next)
}
type link struct {
handler MiddlewareHandler
next *link
}
func (l link) Call(env map[string]interface{}) {
l.handler.Call(env, l.next.Call)
}
// Chain acts as a list of MiddlewareHandler constructors.
// Chain is effectively immutable:
// once created, it will always hold
// the same set of constructors in the same order.
type Chain struct {
handlers []MiddlewareHandler
links link
}
// New creates a new chain,
// memorizing the given list of middleware constructors.
// New serves no other function,
// constructors are only called upon a call to Then().
func New(handlers ...func(map[string]interface{}, HandlerFunc)) *Chain {
var middlewareHandlers []MiddlewareHandler
for _, h := range handlers {
middlewareHandlers = append(middlewareHandlers, MiddlewareHandlerFunc(h))
}
return &Chain{
handlers: middlewareHandlers,
links: build(middlewareHandlers),
}
}
func (c *Chain) Call(env map[string]interface{}) {
c.links.Call(env)
}
func (c *Chain) Use(handlers ...MiddlewareHandler) {
for _, handler := range handlers {
c.handlers = append(c.handlers, handler)
c.links = build(c.handlers)
}
}
func (c *Chain) UseFunc(handlers ...func(env map[string]interface{}, next HandlerFunc)) {
for _, handler := range handlers {
c.Use(MiddlewareHandlerFunc(handler))
}
}
func build(handlers []MiddlewareHandler) link {
var next link
if len(handlers) == 0 {
return defaultMiddlewareLink
} else if len(handlers) > 1 {
next = build(handlers[1:])
} else {
next = defaultMiddlewareLink
}
return link{handlers[0], &next}
}
type NoopMiddlewareHandler struct {
}
func (h NoopMiddlewareHandler) Call(env map[string]interface{}, next HandlerFunc) {
// noop
}
var defaultMiddlewareLink = link{NoopMiddlewareHandler{}, &link{}}