forked from julienschmidt/httprouter
-
Notifications
You must be signed in to change notification settings - Fork 2
/
namespace.go
133 lines (119 loc) · 3.73 KB
/
namespace.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
package httprouter
// Namespace is a struct that can hold muliple routes and sub namespace
type Namespace struct {
Name string
Routes []*NamespaceRoute
ChildNamespaces []*Namespace
IsRoot bool
}
// Route is a struct that can hold route information such as HttpMethod, Path, and Handle func
// Example : &Route{Path: "/",HttpMethod: "POST", Handle: func(http.ResponseWriter, *http.Request, Params)}
type NamespaceRoute struct {
Path string
HttpMethod string
Func Handle
}
// Namespace is a struct that can hold muliple routes and sub namespace
// Route is a struct that can hold route information such as HttpMethod, Path, and Handle func
// Example : &Route{Path: "/",HttpMethod: "POST", Handle: func(http.ResponseWriter, *http.Request, Params)}
type Route struct {
Path string
HttpMethod string
Func Handle
}
// New is a func to create a namespace as root
// It can have multiple sub-namespace
// No namespace on top of root
func NewNamespace(name string) *Namespace {
return &Namespace{
Name: name,
IsRoot: true,
}
}
// RouteTo is to keep the route information in namespace
func (n *Namespace) RouteTo(httpMethod, path string, handle Handle) {
n.Routes = append(n.Routes, &NamespaceRoute{Path: path, HttpMethod: httpMethod, Func: handle})
}
// Handle the route from namaspace
func (root *Namespace) Handle(r *Router) {
if root.IsRoot == true {
root.handleRoutesFromNamespace(root.Name, r)
if root.hasChildNamespaces() {
for _, namespace := range root.ChildNamespaces {
namespace.handleRoutesFromNamespace(namespace.Name, r)
if namespace.hasChildNamespaces() {
handleChildNamespaces(namespace.ChildNamespaces, r)
}
}
}
} else {
panic("Namespace is not root. Use RootNamespace function to create as root.")
}
}
// Check namespace have childs
func (n *Namespace) hasChildNamespaces() bool {
return len(n.ChildNamespaces) > 0
}
// Handle routes for child namespace
func handleChildNamespaces(childs []*Namespace, r *Router) {
for _, child := range childs {
child.handleRoutesFromNamespace(child.Name, r)
if child.hasChildNamespaces() {
handleChildNamespaces(child.ChildNamespaces, r)
}
}
}
// put routes to handler
func (n *Namespace) handleRoutesFromNamespace(prefix string, r *Router) {
for _, route := range n.Routes {
switch route.HttpMethod {
case "GET":
r.GET(prefix+route.Path, route.Func)
case "POST":
r.POST(prefix+route.Path, route.Func)
case "OPTIONS":
r.OPTIONS(prefix+route.Path, route.Func)
case "HEAD":
r.HEAD(prefix+route.Path, route.Func)
case "PUT":
r.PUT(prefix+route.Path, route.Func)
case "PATCH":
r.PATCH(prefix+route.Path, route.Func)
case "DELETE":
r.DELETE(prefix+route.Path, route.Func)
default:
panic("Invalid http method in routes")
}
}
}
// Use is to add sub-namespace for a namesapce
func (n *Namespace) Use(name string) *Namespace {
newPath := n.Name + name
subNamespace := &Namespace{Name: newPath}
n.ChildNamespaces = append(n.ChildNamespaces, subNamespace)
return subNamespace
}
func (r *Router) HandleNamespace(root *Namespace) {
if root.IsRoot == true {
root.handleRoutesFromNamespace(root.Name, r)
if root.hasChildNamespaces() {
for _, namespace := range root.ChildNamespaces {
namespace.handleRoutesFromNamespace(root.Name+namespace.Name, r)
if namespace.hasChildNamespaces() {
handleChildNamespaces(namespace.ChildNamespaces, r)
}
}
}
} else {
panic("Namespace is not root. Use RootNamespace function to create as root.")
}
}
// RootNamespace is a func to create a namespace as root
// RootNamespace can have multiple sub-namespace
// No namespace on top of root
func RootNamespace(name string) *Namespace {
return &Namespace{
Name: name,
IsRoot: true,
}
}