forked from stretchr/goweb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
map.go
213 lines (205 loc) · 7.47 KB
/
map.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
package goweb
import (
"github.com/stretchr/goweb/handlers"
)
// Map adds a new mapping to the DefaultHttpHandler.
//
// The Map function has many flavours.
//
// 1. Implementing and passing in your own handlers.Handler object will just map the handler
// directly.
//
// 2. The path pattern, and the handler function, followed by any optional matcher funcs will cause
// the func to be executed when the path pattern matches.
//
// (pathPattern, func [, matcherFuncs])
//
// 3. The HTTP method (or an array of HTTP methods), the path pettern, the handler function, followed by
// optional matcher funcs will cause the func to be executed when the path and HTTP method match.
//
// (method|methods, pathPattern, func [, matcherFuncs])
//
// 4. Just the handler function, and any optional matcher funcs will add a catch-all handler. This should
// be the last call to Map that you make.
//
// (func [, matcherFuncs])
//
// Each matcherFunc argument can be one of three types:
// 1) handlers.MatcherFunc
// 2) []handlers.MatcherFunc
// 3) func(context.Context) (MatcherFuncDecision, error)
//
// Examples
//
// The following code snippets are real examples of how to use the Map function:
//
// // POST /events
// handler.Map(http.MethodPost, "/events", func(c context.Context) error {
//
// // TODO: Add an event
//
// // no errors
// return nil
//
// })
//
// // POST|PUT /events
// handler.Map([]string{http.MethodPost, http.MethodPut}, "/events", func(c context.Context) error {
//
// // TODO: Add an event
//
// // no errors
// return nil
//
// })
//
// // POST|PUT|DELETE|GET /articles/2013/05/01
// handler.Map("/articles/{year}/{month}/{day}", func(c context.Context) error {
//
// day := c.PathParams().Get("day")
// month := c.PathParams().Get("month")
// year := c.PathParams().Get("year")
//
// // show the articles for the specified day
//
// // no errors
// return nil
//
// })
//
// // All requests
// handler.Map(func(c context.Context) error {
//
// // everything else is a 404
// goweb.Respond.WithStatus(c, http.StatusNotFound)
//
// // no errors
// return nil
//
// })
//
// For a full overview of valid paths, see the "Mapping paths" section above.
func Map(options ...interface{}) (handlers.Handler, error) {
return DefaultHttpHandler().Map(options...)
}
// MapBefore adds a new mapping to the DefaultHttpHandler that
// will be executed before other handlers.
//
// The usage is the same as the goweb.Map function.
//
// Before handlers are called before any of the normal handlers,
// and before any processing has begun. Setting headers is appropriate
// for before handlers, but be careful not to actually write anything or
// Goweb will likely end up trying to write the headers twice and headers set
// in the processing handlers will have no effect.
func MapBefore(options ...interface{}) (handlers.Handler, error) {
return DefaultHttpHandler().MapBefore(options...)
}
// MapAfter adds a new mapping to the DefaultHttpHandler that
// will be executed after other handlers.
//
// The usage is the same as the goweb.Map function.
//
// After handlers are called after the normal processing handlers are
// finished, and usually after the response has been written. Setting headers
// or writing additional bytes will have no effect in after handlers.
func MapAfter(options ...interface{}) (handlers.Handler, error) {
return DefaultHttpHandler().MapAfter(options...)
}
// MapController maps a controller in the handler.
//
// A controller is any object that implements one or more of the controllers.Restful*
// interfaces.
//
// They include:
//
// RestfulController.Path(context.Context) string
// RestfulCreator.Create(context.Context) error
// RestfulReader.Read(context.Context) error
// RestfulManyReader.ReadMany(context.Context) error
// RestfulDeletor.Delete(id string, context.Context) error
// RestfulManyDeleter.DeleteMany(context.Context) error
// RestfulUpdater.Update(id string, context.Context) error
// RestfulReplacer.Replace(id string, context.Context) error
// RestfulManyUpdater.UpdateMany(context.Context) error
// RestfulOptions.Options(context.Context) error
// RestfulHead.Head(context.Context) error
//
// Optionally, you can map Before and After methods too, to allow controller specific
// code to run at appropriate times:
//
// BeforeHandler.Before(context.Context) error
// AfterHandler.After(context.Context) error
//
// To implement any of these methods, you just need to provide a method with the
// same name and signature. For example, a simple RESTful controller that just
// provides a simple GET might look like this:
//
// type MyController struct{}
//
// func (c *MyController) ReadMany(ctx context.Context) error {
// // TODO: do something
// }
//
// The above code would map only `GET /my`.
//
// Controller Paths
//
// This code will map the controller and use the Path() method on the
// controller to determine the path prefix (or it will try to guess the URL part
// based on the name of the struct):
//
// MapController(controller)
//
// This code will map the controller to the specified path prefix regardless
// of what the Path() method returns:
//
// MapController(path, controller)
//
// Optionally, you can pass matcherFuncs as optional additional arguments. See
// goweb.Map() for details on the types of arguments allowed.
func MapController(options ...interface{}) error {
return DefaultHttpHandler().MapController(options...)
}
// MapStatic maps static files from the specified systemPath to the
// specified publicPath.
//
// goweb.MapStatic("/static", "location/on/system/to/files")
//
// Goweb will automatically expand the above public path pattern from `/static` to
// `/static/***` to ensure subfolders are automatcially mapped.
//
// Paths
//
// The systemPath is relative to where you will actually run your app from, for
// example if I am doing `go run main.go` inside the `example_webapp` folder, then
// `./` would refer to the `example_webapp` folder itself. Therefore, to map to the
// `static-files` subfolder, you just need to specify the name of the directory:
//
// goweb.MapStatic("/static", "static-files")
//
// In some cases, your systemPath might be different for development and production
// and this is something to watch out for.
//
// Optionally, you can pass arguments of type MatcherFunc after the second
// argument. Unlike goweb.Map, these can only be of type MatcherFunc.
func MapStatic(publicPath, systemPath string, matcherFuncs ...handlers.MatcherFunc) (handlers.Handler, error) {
return DefaultHttpHandler().MapStatic(publicPath, systemPath, matcherFuncs...)
}
// MapStaticFile maps a static file from the specified staticFilePath to the
// specified publicPath.
//
// goweb.MapStaticFile("favicon.ico", "/location/on/system/to/icons/favicon.ico")
//
// Only paths matching exactly publicPath will cause the single file specified in
// staticFilePath to be delivered to clients.
//
// Optionally, you can pass arguments of type MatcherFunc after the second
// argument. Unlike goweb.Map, these can only be of type MatcherFunc.
func MapStaticFile(publicPath, staticFilePath string, matcherFuncs ...handlers.MatcherFunc) (handlers.Handler, error) {
return DefaultHttpHandler().MapStaticFile(publicPath, staticFilePath, matcherFuncs...)
}
/*
DEVNOTE: These functions are not tested because it simply passes the call on to the
DefaultHttpHandler.
*/