-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.go
96 lines (73 loc) · 2.18 KB
/
router.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
package drouter
import "context"
// Param is a single URL parameter, consisting of a key and a value.
type Param struct {
Key string
Value string
}
// Params is a Param-slice, as returned by the router.
// The slice is ordered, the first URL parameter is also the first slice value.
// It is therefore safe to read values by the index.
type Params []Param
// ByName returns the value of the first Param which key matches the given name.
// If no matching Param is found, an empty string is returned.
func (ps Params) ByName(name string) string {
for _, p := range ps {
if p.Key == name {
return p.Value
}
}
return ""
}
type paramsKey struct{}
var ParamsKey = paramsKey{}
// ParamsFromContext pulls the URL parameters from a request context,
// or returns nil if none are present.
func ParamsFromContext(ctx context.Context) Params {
p, _ := ctx.Value(ParamsKey).(Params)
return p
}
// MatchedRoutePathParam is the Param name under which the path of the matched
// route is stored, if Router.SaveMatchedRoutePath is set.
var MatchedRoutePathParam = "$matchedRoutePath"
// MatchedRoutePath retrieves the path of the matched route.
// Router.SaveMatchedRoutePath must have been enabled when the respective
// handle was added, otherwise this function always returns an empty string.
func (ps Params) MatchedRoutePath() string {
return ps.ByName(MatchedRoutePathParam)
}
type Handle interface{}
type Router struct {
root *node
}
func New() *Router {
return &Router{}
}
func (r *Router) Lookup(path string, params *Params) (Handle, bool) {
root := r.root
if root == nil {
return nil, false
}
handle, tsr := root.getValue(path, params)
if params == nil {
return handle, tsr
}
return handle, tsr
}
func (r *Router) AddRoute(path string, handle Handle) {
if len(path) < 1 || path[0] != '/' {
panic("path must begin with '/' in path '" + path + "'")
}
if handle == nil {
panic("handle must not be nil")
}
root := r.root
if root == nil {
root = new(node)
r.root = root
}
root.addRoute(path, handle)
}
func (r *Router) FindCaseInsensitivePath(path string, fixTrailingSlash bool) (fixedPath string, found bool) {
return r.root.findCaseInsensitivePath(path, fixTrailingSlash)
}