/
doze.go
61 lines (50 loc) · 1.54 KB
/
doze.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
package doze
import (
"net/http"
)
// Routeable is an interface which allows you to create your own router
// * Get(string) *Route returns the route by route name
// * Match(string) *Route takes a URI and returns a *Route it matches. If it does not
// it returns nil
type Routeable interface {
Get(string) PatternedRoute
Match(string) (PatternedRoute, bool)
}
// ActionFunc is a type that is a function to be used as a controller action
type ActionFunc func(*Context) ResponseSender
// Handler implements http.Handler and contains the router and controllers for the REST api
type Handler struct {
router Routeable
middleware []MiddlewareFunc
}
// NewHandler returns a new Handler with router initialized
func NewHandler(r Routeable) *Handler {
return &Handler{router: r}
}
// Use applies a MiddlewareFunc to be executed in the request chain
func (h *Handler) Use(mf MiddlewareFunc) {
h.middleware = append(h.middleware, mf)
}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
route, matched := h.router.Match(r.URL.Path)
if !matched {
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
return
}
action, actionExists := route.Actions()[r.Method]
if !actionExists {
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
return
}
context := &Context{
Request: r,
ResponseWriter: &ResponseWriter{w, 0, 0},
Route: route,
}
mwc := &middlewareChain{action: action}
for _, mw := range h.middleware {
mwc.add(mw)
}
mwc.run(context)
return
}