-
Notifications
You must be signed in to change notification settings - Fork 10
/
controller.go
111 lines (89 loc) · 2.65 KB
/
controller.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
package service
import (
"fmt"
"log"
"net/http"
"strings"
"github.com/cloudflare/service/render"
)
// WebController describes the HTTP method handlers for a given route.
// Create a WebController with service.NewController(route)
type WebController struct {
Route string
handlers map[int]func(w http.ResponseWriter, req *http.Request)
allowed string
}
// NewWebController creates a new controller for a given route
func NewWebController(route string) WebController {
wc := WebController{}
wc.handlers = make(map[int]func(w http.ResponseWriter, req *http.Request))
wc.Route = route
return wc
}
// GetAllowedMethods returns a comma-delimited string of HTTP methods allowed by
// this controller. This is determined by examining which methods have handlers
// assigned to them.
func (wc *WebController) GetAllowedMethods() string {
if wc.allowed != "" {
return wc.allowed
}
allowed := []string{}
for k := range wc.handlers {
allowed = append(allowed, GetMethodName(k))
}
wc.allowed = strings.Join(allowed, ",")
return wc.allowed
}
// AddMethodHandler adds a HTTP handler to a given HTTP method
func (wc *WebController) AddMethodHandler(m int, h func(w http.ResponseWriter, req *http.Request)) {
if !IsMethod(m) {
log.Fatalf("Method iota %d not recognised", m)
}
if m == Options {
log.Fatal("Cannot set OPTIONS, this is provided for you")
}
if m == Head {
log.Fatal("Cannot set HEAD, this is provided for you")
}
wc.handlers[m] = h
wc.allowed = ""
}
// GetMethodHandler returns the appropriate method handler for the request or a
// Method Not Allowed handler
func (wc *WebController) GetMethodHandler(m int) func(w http.ResponseWriter, req *http.Request) {
if m == Options {
return func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Allow", wc.GetAllowedMethods())
w.Header().Set("Content-Length", "0")
w.WriteHeader(http.StatusOK)
}
}
if m == Head {
return func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Allow", wc.GetAllowedMethods())
w.Header().Set("Content-Length", "0")
w.WriteHeader(http.StatusOK)
}
}
if h, ok := wc.handlers[m]; ok {
return h
}
return func(w http.ResponseWriter, req *http.Request) {
allowed := wc.GetAllowedMethods()
w.Header().Set("Allow", allowed)
render.Error(
w,
http.StatusMethodNotAllowed,
fmt.Errorf("405 Method Not Allowed. Allowed: %s", allowed),
)
}
}
// GetHandler returns a global handler for this route, to be used by the server
// mux
func GetHandler(
wc WebController,
) func(w http.ResponseWriter, req *http.Request) {
return func(w http.ResponseWriter, req *http.Request) {
wc.GetMethodHandler(GetHTTPMethod(req))(w, req)
}
}