-
Notifications
You must be signed in to change notification settings - Fork 38
/
routing.go
57 lines (48 loc) · 1.37 KB
/
routing.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
package mango
import (
"regexp"
"sort"
)
// Methods required by sort.Interface.
type matcherArray []*regexp.Regexp
func specificity(matcher *regexp.Regexp) int {
return len(matcher.String())
}
func (this matcherArray) Len() int {
return len(this)
}
func (this matcherArray) Less(i, j int) bool {
// The sign is reversed below so we sort the matchers in descending order
return specificity(this[i]) > specificity(this[j])
}
func (this matcherArray) Swap(i, j int) {
this[i], this[j] = this[j], this[i]
}
func Routing(routes map[string]App) Middleware {
matchers := matcherArray{}
handlers := []App{}
// Compile the matchers
for matcher, _ := range routes {
// compile the matchers
matchers = append([]*regexp.Regexp(matchers), regexp.MustCompile(matcher))
}
// sort 'em by descending length
sort.Sort(matchers)
// Attach the handlers to each matcher
for _, matcher := range matchers {
// Attach them to their handlers
handlers = append(handlers, routes[matcher.String()])
}
return func(env Env, app App) (Status, Headers, Body) {
for i, matcher := range matchers {
matches := matcher.FindStringSubmatch(env.Request().URL.Path)
if len(matches) != 0 {
// Matched a route; inject matches and return handler
env["Routing.matches"] = matches
return handlers[i](env)
}
}
// didn't match any of the other routes. pass upstream.
return app(env)
}
}