forked from Necroforger/dgrouter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dgrouter.go
141 lines (123 loc) · 3.31 KB
/
dgrouter.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package dgrouter
import (
"errors"
)
// Error variables
var (
ErrCouldNotFindRoute = errors.New("Could not find route")
ErrRouteAlreadyExists = errors.New("route already exists")
)
// HandlerFunc is a command handler
type HandlerFunc func(interface{})
// MiddlewareFunc is a middleware
type MiddlewareFunc func(HandlerFunc) HandlerFunc
// Group allows you to do things like more easily manage categories
// For example, setting the routes category in the callback will cause
// All future added routes to inherit the category.
// example:
// Group(func (r *Route) {
// r.Cat("stuff")
// r.On("thing", nil).Desc("the category of this function will be stuff")
// })
func (r *Route) Group(fn func(r *Route)) *Route {
rt := New()
fn(rt)
for _, v := range rt.Routes {
r.AddRoute(v)
}
return r
}
// Use adds the given middleware func to this route's middleware chain
func (r *Route) Use(fn ...MiddlewareFunc) *Route {
r.Middleware = append(r.Middleware, fn...)
return r
}
// On registers a route with the name you supply
// name : name of the route to create
// handler : handler function
func (r *Route) On(name string, handler HandlerFunc) *Route {
rt := r.OnMatch(name, nil, handler)
rt.Matcher = NewNameMatcher(rt)
return rt
}
// OnMatch adds a handler for the given route
// name : name of the route to add
// matcher : matcher function used to match the route
// handler : handler function for the route
func (r *Route) OnMatch(name string, matcher func(string) bool, handler HandlerFunc) *Route {
if rt := r.Find(name); rt != nil {
return rt
}
nhandler := handler
// Add middleware to the handler
for _, v := range r.Middleware {
nhandler = v(nhandler)
}
rt := &Route{
Name: name,
Category: r.Category,
Handler: nhandler,
Matcher: matcher,
}
r.AddRoute(rt)
return rt
}
// AddRoute adds a route to the router
// Will return RouteAlreadyExists error on failure
// route : route to add
func (r *Route) AddRoute(route *Route) error {
// Check if the route already exists
if rt := r.Find(route.Name); rt != nil {
return ErrRouteAlreadyExists
}
route.Parent = r
r.Routes = append(r.Routes, route)
return nil
}
// RemoveRoute removes a route from the router
// route : route to remove
func (r *Route) RemoveRoute(route *Route) error {
for i, v := range r.Routes {
if v == route {
r.Routes = append(r.Routes[:i], r.Routes[i+1:]...)
return nil
}
}
return ErrCouldNotFindRoute
}
// Find finds a route with the given name
// It will return nil if nothing is found
// name : name of route to find
func (r *Route) Find(name string) *Route {
for _, v := range r.Routes {
if v.Matcher(name) {
return v
}
}
return nil
}
// FindFull a full path of routes by searching through their subroutes
// Until the deepest match is found.
// It will return the route matched and the depth it was found at
// args : path of route you wish to find
// ex. FindFull(command, subroute1, subroute2, nonexistent)
// will return the deepest found match, which will be subroute2
func (r *Route) FindFull(args ...string) (*Route, int) {
nr := r
i := 0
for _, v := range args {
if rt := nr.Find(v); rt != nil {
nr = rt
i++
} else {
break
}
}
return nr, i
}
// New returns a new route
func New() *Route {
return &Route{
Routes: []*Route{},
}
}