-
Notifications
You must be signed in to change notification settings - Fork 0
/
route.go
131 lines (110 loc) · 3.84 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
package stgin
import (
"net/http"
"regexp"
"strings"
)
// API is the lowest-level functionality in stgin.
// It represents a function which takes a request, and generates an HTTP response.
type API = func(c RequestContext) Status
// Route is a struct which specifies whether a request should be handled by the given Action inside the route.
type Route struct {
Path string
Method string
Action API
correspondingRegex *regexp.Regexp
controller *Controller
dir string
expectedQueries queryDecl
}
func (route Route) isStaticDir() bool { return route.dir != "" }
func (route Route) acceptsAndPathParams(request *http.Request) (bool, Params) {
var ok bool
var params Params
if request.Method == route.Method {
params, ok = matchAndExtractPathParams(&route, request.URL.Path)
}
return ok, params
}
func getRoutePatternRegexOrPanic(pattern string) *regexp.Regexp {
regex, err := getPatternCorrespondingRegex(pattern)
if err != nil {
panic(err)
}
return regex
}
func mkRoute(pattern string, api API, method string) Route {
if api == nil {
printStacktrace("")
panic("cannot use nil as an API action")
}
path, queryDefs := splitBy(pattern, "?")
return Route{
Path: path,
Method: method,
Action: api,
expectedQueries: getQueryDefinitionsFromPattern(queryDefs),
}
}
// GET is a shortcut to define a route with http "GET" method.
func GET(pattern string, api API) Route {
return mkRoute(pattern, api, "GET")
}
// PUT is a shortcut to define a route with http "PUT" method.
func PUT(pattern string, api API) Route {
return mkRoute(pattern, api, "PUT")
}
// POST is a shortcut to define a route with http "POST" method.
func POST(pattern string, api API) Route {
return mkRoute(pattern, api, "POST")
}
// DELETE is a shortcut to define a route with http "DELETE" method.
func DELETE(pattern string, api API) Route {
return mkRoute(pattern, api, "DELETE")
}
// PATCH is a shortcut to define a route with http "PATCH" method.
func PATCH(pattern string, api API) Route {
return mkRoute(pattern, api, "PATCH")
}
// OPTIONS is a shortcut to define a route with http "OPTIONS" method.
func OPTIONS(pattern string, api API) Route {
return mkRoute(pattern, api, "OPTIONS")
}
// Prefix can be used as a pattern inside route definition, which matches all the requests that contain the given prefix.
// Note that this is appended to the corresponding controller's prefix in which the route is defined.
func Prefix(path string) string {
return normalizePath("/" + path + "/.*")
}
// StaticDir can be used to server static directories.
// It's better to use StaticDir inside the server itself, or to have a dedicated controller for static directories you
// would want to serve.
func StaticDir(pattern string, dir string) Route {
return Route{
Path: normalizePath("/" + pattern + "/"),
Method: "GET",
dir: dir,
}
}
// Handle is a generic function that can be used for other http methods that do not have a helper function in stgin (like GET).
func Handle(method string, pattern string, api API) Route {
return mkRoute(pattern, api, method)
}
// RouteCreationStage is a struct that can make routes step by step.
// Is only returned after OnPath function is called.
type RouteCreationStage struct {
method string
path string
}
// Do assign's the api action to the route creation stage, and returns the resulting route.
func (stage RouteCreationStage) Do(api API) Route {
return mkRoute(stage.path, api, strings.ToUpper(stage.method))
}
// OnPath is the starting point of route creation stage, specifies the pattern.
func OnPath(path string) RouteCreationStage {
return RouteCreationStage{path: path}
}
// WithMethod attaches the method to the route creation stage.
func (stage RouteCreationStage) WithMethod(method string) RouteCreationStage {
stage.method = method
return stage
}