-
Notifications
You must be signed in to change notification settings - Fork 16
/
router.go
108 lines (86 loc) · 2.66 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
97
98
99
100
101
102
103
104
105
106
107
108
package jsonrpc
import (
"errors"
)
// ErrNotFound is returned when no route match is found.
var ErrNotFound = errors.New("no matching route was found")
type Router struct {
// DefaultHandler to be used when no route matches.
defaultHandler Handler
// Routes to be matched, in order.
routes []*Route
// Routes matching a given method name for fast look-up
methodRoutes map[string][]*Route
matchers []matcher
}
// NewRouter returns a new router instance.
func NewRouter() *Router {
return &Router{methodRoutes: make(map[string][]*Route)}
}
func (r *Router) Match(msg *RequestMsg, match *RouteMatch) bool {
methodRoutes, ok := r.methodRoutes[msg.Method]
if ok {
for _, route := range methodRoutes {
if route.Match(msg, match) {
return true
}
}
}
for _, route := range r.routes {
if route.Match(msg, match) {
return true
}
}
// Closest match for a router (includes sub-routers)
if r.defaultHandler != nil {
match.Handler = r.defaultHandler
return true
}
match.Err = ErrNotFound
return false
}
// NewRoute registers an empty route.
func (r *Router) NewRoute() *Route {
// initialize a route with a copy of the parent router's configuration
route := &Route{methodRoutes: r.methodRoutes, matchers: make([]matcher, len(r.matchers))}
r.routes = append(r.routes, route)
copy(route.matchers, r.matchers)
return route
}
// Handle registers a new route for a given method
func (r *Router) Handle(method string, handler Handler) *Route {
return r.NewRoute().Method(method).Handle(handler)
}
// HandleFunc registers a new route for a given method
func (r *Router) HandleFunc(method string, f func(ResponseWriter, *RequestMsg)) *Route {
return r.NewRoute().Method(method).HandleFunc(f)
}
// Version registers a new route with a matcher for given JSON-RPC version
func (r *Router) DefaultHandler(handler Handler) *Router {
r.defaultHandler = handler
return r
}
// Method registers a new route with a matcher for given method
func (r *Router) Method(method string) *Route {
return r.NewRoute().Method(method)
}
// MethodPrefix registers a new route with a matcher for given method
func (r *Router) MethodPrefix(prefix string) *Route {
return r.NewRoute().MethodPrefix(prefix)
}
// Version registers a new route with a matcher for given JSON-RPC version
func (r *Router) Version(version string) *Route {
return r.NewRoute().Version(version)
}
// ServeRPC dispatches the handler registered in the matched route.
func (r *Router) ServeRPC(rw ResponseWriter, msg *RequestMsg) {
var match RouteMatch
var handler Handler
if r.Match(msg, &match) {
handler = match.Handler
}
if handler == nil {
handler = MethodNotFoundHandler()
}
handler.ServeRPC(rw, msg)
}