github.com/conradwt/buffalo@v0.11.1/route.go (about) 1 package buffalo 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "html/template" 7 "net/url" 8 "sort" 9 "strings" 10 11 "reflect" 12 13 "github.com/gorilla/mux" 14 "github.com/markbates/inflect" 15 ) 16 17 // Routes returns a list of all of the routes defined 18 // in this application. 19 func (a *App) Routes() RouteList { 20 if a.root != nil { 21 return a.root.routes 22 } 23 return a.routes 24 } 25 26 // RouteInfo provides information about the underlying route that 27 // was built. 28 type RouteInfo struct { 29 Method string `json:"method"` 30 Path string `json:"path"` 31 HandlerName string `json:"handler"` 32 PathName string `json:"pathName"` 33 Aliases []string `json:"aliases"` 34 MuxRoute *mux.Route `json:"-"` 35 Handler Handler `json:"-"` 36 App *App `json:"-"` 37 } 38 39 // String returns a JSON representation of the RouteInfo 40 func (ri RouteInfo) String() string { 41 b, _ := json.MarshalIndent(ri, "", " ") 42 return string(b) 43 } 44 45 // Alias path patterns to the this route. This is not the 46 // same as a redirect. 47 func (ri *RouteInfo) Alias(aliases ...string) *RouteInfo { 48 ri.Aliases = append(ri.Aliases, aliases...) 49 for _, a := range aliases { 50 ri.App.router.Handle(a, ri).Methods(ri.Method) 51 } 52 return ri 53 } 54 55 // Name allows users to set custom names for the routes. 56 func (ri *RouteInfo) Name(name string) *RouteInfo { 57 routeIndex := -1 58 for index, route := range ri.App.Routes() { 59 if route.Path == ri.Path && route.Method == ri.Method { 60 routeIndex = index 61 break 62 } 63 } 64 65 name = inflect.CamelizeDownFirst(name) 66 67 if !strings.HasSuffix(name, "Path") { 68 name = name + "Path" 69 } 70 71 ri.PathName = name 72 if routeIndex != -1 { 73 ri.App.Routes()[routeIndex] = reflect.ValueOf(ri).Interface().(*RouteInfo) 74 } 75 76 return ri 77 } 78 79 //BuildPathHelper Builds a routeHelperfunc for a particular RouteInfo 80 func (ri *RouteInfo) BuildPathHelper() RouteHelperFunc { 81 cRoute := ri 82 return func(opts map[string]interface{}) template.HTML { 83 pairs := []string{} 84 for k, v := range opts { 85 pairs = append(pairs, k) 86 pairs = append(pairs, fmt.Sprintf("%v", v)) 87 } 88 89 url, err := cRoute.MuxRoute.URL(pairs...) 90 if err != nil { 91 return template.HTML(cRoute.Path) 92 } 93 94 result := url.Path 95 result = addExtraParamsTo(result, opts) 96 97 return template.HTML(result) 98 } 99 } 100 101 func addExtraParamsTo(path string, opts map[string]interface{}) string { 102 pendingParams := map[string]string{} 103 keys := []string{} 104 for k, v := range opts { 105 if strings.Contains(path, fmt.Sprintf("%v", v)) { 106 continue 107 } 108 109 keys = append(keys, k) 110 pendingParams[k] = fmt.Sprintf("%v", v) 111 } 112 113 if len(keys) == 0 { 114 return path 115 } 116 117 if strings.Contains(path, "?") == false { 118 path = path + "?" 119 } else { 120 if strings.HasSuffix(path, "?") == false { 121 path = path + "&" 122 } 123 } 124 125 sort.Strings(keys) 126 127 for index, k := range keys { 128 format := "%v=%v" 129 130 if index > 0 { 131 format = "&%v=%v" 132 } 133 134 path = path + fmt.Sprintf(format, url.QueryEscape(k), url.QueryEscape(pendingParams[k])) 135 } 136 137 return path 138 } 139 140 //RouteHelperFunc represents the function that takes the route and the opts and build the path 141 type RouteHelperFunc func(opts map[string]interface{}) template.HTML 142 143 // RouteList contains a mapping of the routes defined 144 // in the application. This listing contains, Method, Path, 145 // and the name of the Handler defined to process that route. 146 type RouteList []*RouteInfo 147 148 func (a RouteList) Len() int { return len(a) } 149 func (a RouteList) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 150 func (a RouteList) Less(i, j int) bool { 151 x := a[i].Path // + a[i].Method 152 y := a[j].Path // + a[j].Method 153 return x < y 154 }