-
-
Notifications
You must be signed in to change notification settings - Fork 366
/
route.go
90 lines (75 loc) · 1.86 KB
/
route.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
package app
import (
"reflect"
"regexp"
"sync"
)
var (
routes = makeRouter()
)
// Route associates the type of the given component to the given path.
//
// When a page is requested and matches the route, a new instance of the given
// component is created before being displayed.
func Route(path string, c Composer) {
routes.route(path, c)
}
// RouteWithRegexp associates the type of the given component to the given
// regular expression pattern.
//
// Patterns use the Go standard regexp format.
//
// When a page is requested and matches the pattern, a new instance of the given
// component is created before being displayed.
func RouteWithRegexp(pattern string, c Composer) {
routes.routeWithRegexp(pattern, c)
}
type router struct {
mu sync.RWMutex
routes map[string]reflect.Type
routesWithRegexp []regexpRoute
}
func makeRouter() router {
return router{
routes: make(map[string]reflect.Type),
}
}
func (r *router) route(path string, c Composer) {
r.mu.Lock()
defer r.mu.Unlock()
r.routes[path] = reflect.TypeOf(c)
}
func (r *router) routeWithRegexp(pattern string, c Composer) {
r.mu.Lock()
defer r.mu.Unlock()
r.routesWithRegexp = append(r.routesWithRegexp, regexpRoute{
regexp: regexp.MustCompile(pattern),
compoType: reflect.TypeOf(c),
})
}
func (r *router) createComponent(path string) (Composer, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
compoType, isRouted := r.routes[path]
if !isRouted {
for _, rwr := range r.routesWithRegexp {
if rwr.regexp.MatchString(path) {
compoType = rwr.compoType
isRouted = true
break
}
}
}
if !isRouted {
return nil, false
}
compo := reflect.New(compoType.Elem()).Interface().(Composer)
return compo, true
}
func (r *router) len() int {
return len(r.routes) + len(r.routesWithRegexp)
}
type regexpRoute struct {
regexp *regexp.Regexp
compoType reflect.Type
}