forked from gobuffalo/buffalo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
route_info.go
121 lines (101 loc) · 2.85 KB
/
route_info.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
package buffalo
import (
"encoding/json"
"errors"
"fmt"
"html/template"
"net/http"
"reflect"
"strings"
"github.com/gobuffalo/flect"
"github.com/gobuffalo/events"
"github.com/gorilla/mux"
)
// 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"`
ResourceName string `json:"resourceName,omitempty"`
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.App.host == ri.App.host && route.Path == ri.Path && route.Method == ri.Method {
routeIndex = index
break
}
}
name = flect.Camelize(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, error) {
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 "", fmt.Errorf("missing parameters for %v: %s", cRoute.Path, err)
}
result := url.String()
result = addExtraParamsTo(result, opts)
return template.HTML(result), nil
}
}
func (ri RouteInfo) ServeHTTP(res http.ResponseWriter, req *http.Request) {
a := ri.App
c := a.newContext(ri, res, req)
payload := events.Payload{
"route": ri,
"app": a,
"context": c,
}
events.EmitPayload(EvtRouteStarted, payload)
err := a.Middleware.handler(ri)(c)
if err != nil {
status := http.StatusInternalServerError
var he HTTPError
if errors.As(err, &he) {
status = he.Status
}
events.EmitError(EvtRouteErr, err, payload)
// things have really hit the fan if we're here!!
a.Logger.Error(err)
c.Response().WriteHeader(status)
c.Response().Write([]byte(err.Error()))
}
events.EmitPayload(EvtRouteFinished, payload)
}