forked from gobuffalo/buffalo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
route.go
154 lines (126 loc) · 3.48 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
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
142
143
144
145
146
147
148
149
150
151
152
153
154
package buffalo
import (
"encoding/json"
"fmt"
"html/template"
"net/url"
"sort"
"strings"
"reflect"
"github.com/gorilla/mux"
"github.com/markbates/inflect"
)
// Routes returns a list of all of the routes defined
// in this application.
func (a *App) Routes() RouteList {
if a.root != nil {
return a.root.routes
}
return a.routes
}
// RouteInfo provides information about the underlying route that
// was built.
type RouteInfo struct {
Method string `json:"method"`
Path string `json:"path"`
HandlerName string `json:"handler"`
PathName string `json:"pathName"`
Aliases []string `json:"aliases"`
MuxRoute *mux.Route `json:"-"`
Handler Handler `json:"-"`
App *App `json:"-"`
}
// String returns a JSON representation of the RouteInfo
func (ri RouteInfo) String() string {
b, _ := json.MarshalIndent(ri, "", " ")
return string(b)
}
// Alias path patterns to the this route. This is not the
// same as a redirect.
func (ri *RouteInfo) Alias(aliases ...string) *RouteInfo {
ri.Aliases = append(ri.Aliases, aliases...)
for _, a := range aliases {
ri.App.router.Handle(a, ri).Methods(ri.Method)
}
return ri
}
// Name allows users to set custom names for the routes.
func (ri *RouteInfo) Name(name string) *RouteInfo {
routeIndex := -1
for index, route := range ri.App.Routes() {
if route.Path == ri.Path && route.Method == ri.Method {
routeIndex = index
break
}
}
name = inflect.CamelizeDownFirst(name)
if !strings.HasSuffix(name, "Path") {
name = name + "Path"
}
ri.PathName = name
if routeIndex != -1 {
ri.App.Routes()[routeIndex] = reflect.ValueOf(ri).Interface().(*RouteInfo)
}
return ri
}
//BuildPathHelper Builds a routeHelperfunc for a particular RouteInfo
func (ri *RouteInfo) BuildPathHelper() RouteHelperFunc {
cRoute := ri
return func(opts map[string]interface{}) template.HTML {
pairs := []string{}
for k, v := range opts {
pairs = append(pairs, k)
pairs = append(pairs, fmt.Sprintf("%v", v))
}
url, err := cRoute.MuxRoute.URL(pairs...)
if err != nil {
return template.HTML(cRoute.Path)
}
result := url.Path
result = addExtraParamsTo(result, opts)
return template.HTML(result)
}
}
func addExtraParamsTo(path string, opts map[string]interface{}) string {
pendingParams := map[string]string{}
keys := []string{}
for k, v := range opts {
if strings.Contains(path, fmt.Sprintf("%v", v)) {
continue
}
keys = append(keys, k)
pendingParams[k] = fmt.Sprintf("%v", v)
}
if len(keys) == 0 {
return path
}
if strings.Contains(path, "?") == false {
path = path + "?"
} else {
if strings.HasSuffix(path, "?") == false {
path = path + "&"
}
}
sort.Strings(keys)
for index, k := range keys {
format := "%v=%v"
if index > 0 {
format = "&%v=%v"
}
path = path + fmt.Sprintf(format, url.QueryEscape(k), url.QueryEscape(pendingParams[k]))
}
return path
}
//RouteHelperFunc represents the function that takes the route and the opts and build the path
type RouteHelperFunc func(opts map[string]interface{}) template.HTML
// RouteList contains a mapping of the routes defined
// in the application. This listing contains, Method, Path,
// and the name of the Handler defined to process that route.
type RouteList []*RouteInfo
func (a RouteList) Len() int { return len(a) }
func (a RouteList) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a RouteList) Less(i, j int) bool {
x := a[i].Path // + a[i].Method
y := a[j].Path // + a[j].Method
return x < y
}