-
Notifications
You must be signed in to change notification settings - Fork 0
/
mooxy.go
98 lines (84 loc) · 2.52 KB
/
mooxy.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
package mooxy
import (
"errors"
"net/http"
"net/url"
"strings"
)
type Router struct {
Children map[string]*Router
Handler *http.Handler
AvailableMethods HTTPMethods
}
func (r *Router) Handle (route *Route, handler http.Handler) {
var pathParts = getPathParts(route.Path)
var lastElementIndex = len(pathParts) - 1
currentMatrix := r.Children
for index, p := range pathParts{
var c = currentMatrix[p]
if c == nil {
currentMatrix[p] = NewRouter()
}
if (index == lastElementIndex) {
currentMatrix[p].Handler = &handler
for method := range route.methods.methods {
currentMatrix[p].AvailableMethods.Add(method, handler)
}
}
currentMatrix = currentMatrix[p].Children
}
}
func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// here we will match to the correct handler and ServeHTTP
var foundRouter, err = router.getRouterForUrl(*r.URL)
if (err != nil) {
http.Error(w, err.Error(), 404)
return
}
rt := *foundRouter
if (rt.Handler == nil) {
http.Error(w, "Page not found.", 404)
return
}
if (!rt.AvailableMethods.Has(HTTPMethod(r.Method))) {
http.Error(w, "Method not available", 405)
return
}
handler := rt.AvailableMethods.methods[HTTPMethod(r.Method)]
handler.ServeHTTP(w, r)
}
func (router *Router) getRouterForUrl(u url.URL) (h *Router, er error) {
var path = u.Path
var pathParts = getPathParts(path)
var currentMatrix = router.Children
var routerForPath = router
for _, p := range pathParts {
routerForPath = currentMatrix[p]
if routerForPath == nil {
routerForPath = getVariableRouter(currentMatrix)
if routerForPath == nil {
return nil, errors.New("Page not found.")
}
}
if len(routerForPath.Children) != 0 {
currentMatrix = routerForPath.Children
}
}
return routerForPath, nil
}
func getPathParts(path string) []string {
path = strings.Trim(path, "/")
var pathParts = strings.Split(path, "/")
return pathParts
}
func getVariableRouter(routerList map[string]*Router) (*Router) {
for k, r := range routerList {
if strings.HasPrefix(k, "{") && strings.HasSuffix(k, "}") {
return r
}
}
return nil
}
func NewRouter() *Router {
return &Router{ Children: make(map[string]*Router), AvailableMethods: NewHttpMethods()}
}