-
-
Notifications
You must be signed in to change notification settings - Fork 36
/
middleware.go
105 lines (93 loc) · 3.24 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
103
104
105
package kami
import (
"strings"
"github.com/guregu/kami/treemux"
)
type wares struct {
middleware map[string][]Middleware
afterware map[string][]Afterware
wildcards *treemux.TreeMux
afterWildcards *treemux.TreeMux
}
func newWares() *wares {
return new(wares)
}
// Use registers middleware to run for the given path.
// See the global Use function's documents for information on how middleware works.
func (m *wares) Use(path string, mw MiddlewareType) {
if containsWildcard(path) {
if m.wildcards == nil {
m.wildcards = treemux.New()
}
mw := convert(mw)
iface, _ := m.wildcards.Get(path)
if chain, ok := iface.(*[]Middleware); ok {
*chain = append(*chain, mw)
} else {
chain := []Middleware{mw}
m.wildcards.Set(path, &chain)
}
} else {
if m.middleware == nil {
m.middleware = make(map[string][]Middleware)
}
fn := convert(mw)
chain := m.middleware[path]
chain = append(chain, fn)
m.middleware[path] = chain
}
}
// After registers middleware to run for the given path after normal middleware added with Use has run.
// See the global After function's documents for information on how middleware works.
func (m *wares) After(path string, afterware AfterwareType) {
aw := convertAW(afterware)
if containsWildcard(path) {
if m.afterWildcards == nil {
m.afterWildcards = treemux.New()
}
iface, _ := m.afterWildcards.Get(path)
if chain, ok := iface.(*[]Afterware); ok {
*chain = append([]Afterware{aw}, *chain...)
} else {
chain := []Afterware{aw}
m.afterWildcards.Set(path, &chain)
}
} else {
if m.afterware == nil {
m.afterware = make(map[string][]Afterware)
}
m.afterware[path] = append([]Afterware{aw}, m.afterware[path]...)
}
}
var defaultMW = newWares() // for the global router
// Use registers middleware to run for the given path.
// Middleware will be executed hierarchically, starting with the least specific path.
// Middleware under the same path will be executed in order of registration.
// You may use wildcards in the path. Wildcard middleware will be run last,
// after all hierarchical middleware has run.
//
// Adding middleware is not threadsafe.
//
// WARNING: kami middleware is run in sequence, but standard middleware is chained;
// middleware that expects its code to run after the next handler, such as
// standard loggers and panic handlers, will not work as expected.
// Use kami.LogHandler and kami.PanicHandler instead.
// Standard middleware that does not call the next handler to stop the request is supported.
func Use(path string, mw MiddlewareType) {
defaultMW.Use(path, mw)
}
// After registers afterware to run after middleware and the request handler has run.
// Afterware is like middleware, but everything is in reverse.
// Afterware will be executed hierarchically, starting with wildcards and then
// the most specific path, ending with /.
// Afterware under the same path will be executed in the opposite order of registration.
func After(path string, aw AfterwareType) {
defaultMW.After(path, aw)
}
// Middleware run functions are in versioned files.
func (m *wares) needsWrapper() bool {
return m.afterware != nil || m.afterWildcards != nil
}
func containsWildcard(path string) bool {
return strings.Contains(path, "/:") || strings.Contains(path, "/*")
}