-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathresource.go
More file actions
106 lines (90 loc) · 2.07 KB
/
resource.go
File metadata and controls
106 lines (90 loc) · 2.07 KB
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
package web
import (
"net/http"
"strings"
)
// ResourceHandleFunc is a function that will be given the second path element.
// ResourceHandleFunc is itself an http.Handler.
type ResourceHandleFunc func(string) http.Handler
func (rhf ResourceHandleFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
paths := PathParts(r.URL.Path)
var id string
if len(paths) > 1 {
id = paths[1]
}
rhf(id).ServeHTTP(w, r)
}
type Resource struct {
// Handlers for a resource.
// Index -> GET /prefix/
// Create -> POST /prefix/
// Show -> GET /prefix/:id
// Update -> PATCH /prefix/:id
// Replace -> PUT /prefix/:id
// Delete -> DELETE /prefix/:id
Index,
Create,
Show,
Replace,
Update,
Delete http.Handler
// NotFound is called when given an invalid path
NotFound,
// MethodNotAllowed is called when given an invalid HTTP Method for a path
MethodNotAllowed,
// Handler is called for /prefix/:id/
Handler,
method,
index http.Handler
}
func (rs *Resource) ServeHTTP(w http.ResponseWriter, r *http.Request) {
buildResource(rs)
paths := PathParts(r.URL.Path)
// no resource id
if len(paths) < 2 {
rs.index.ServeHTTP(w, r)
return
}
if len(paths) > 2 {
if rs.Handler == nil {
rs.NotFound.ServeHTTP(w, r)
} else {
rs.Handler.ServeHTTP(w, r)
}
return
}
rs.method.ServeHTTP(w, r)
}
func buildResource(rs *Resource) {
if rs.NotFound == nil {
rs.NotFound = http.NotFoundHandler()
}
if rs.index == nil {
rs.index = &Method{
Get: rs.Index,
Post: rs.Create,
MethodNotAllowed: rs.MethodNotAllowed,
}
}
if rs.method == nil {
rs.method = &Method{
Get: rs.Show,
Patch: rs.Update,
Put: rs.Replace,
Delete: rs.Delete,
MethodNotAllowed: rs.MethodNotAllowed,
}
}
}
// PathParts removes leading and trailing slash, then splits on slash
func PathParts(path string) []string {
// removing leading /
if path[0] == '/' {
path = path[1:]
}
// remove trailing /
if path[len(path)-1] == '/' {
path = path[:len(path)-1]
}
return strings.Split(path, "/")
}