-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.go
executable file
·153 lines (126 loc) · 3.64 KB
/
router.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package goninja
import (
// "fmt"
"net/http"
"reflect"
"regexp"
"strings"
)
type Params map[string]string
type Router struct {
//slice with all routes
routes []Route
test string
//hash with named route that matchers Route object
named_routes map[string]*Route
}
var pattern string = "[a-zA-Z0-9]+"
type Route struct {
method string
pattern string
action string
controller string
}
func NewRouter() *Router {
router := &Router{}
return router
}
func (r *Router) Route(method string, pattern string, action string, controller string, c interface{}) *Router {
route := Route{method, pattern, action, controller}
CreateControllers(controller, c)
r.routes = append(r.routes, route)
return r
}
func (r *Router) RootRoute(action string, controller string, c interface{}) *Router {
return r.Route("GET", "/", action, controller, c)
}
func (router *Router) match(request *http.Request) Route {
var route Route
if strings.Contains(request.URL.Path, "/assets/") {
return route
}
RouteLoop:
for _, r := range router.routes {
LOGGER.Println(request.URL.Path)
if request.URL.Path == "/" {
if r.pattern == "/" {
route = r //root url
break RouteLoop
} else {
continue RouteLoop
}
}
route_pieces := strings.Split(r.pattern, "/")
request_pieces := strings.Split(request.URL.Path, "/")
for i, x := range route_pieces {
if len(x) > 0 && string(x[0]) == ":" {
route_pieces[i] = pattern
}
}
if len(route_pieces) != len(request_pieces) {
continue RouteLoop
}
route_regexp_string := strings.Join(route_pieces, "/")
if route_regexp_string != "/" && regexp.MustCompile(route_regexp_string).MatchString(request.URL.Path) && request.Method == r.method { //WE have matched controller
route = r
break RouteLoop
}
}
return route
}
func (route *Route) ControllerNotFound(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(404)
w.Write([]byte("Controller that matches \"" + r.URL.Path + "\" could not be found"))
}
func (route *Route) CheckRequestMethod(w http.ResponseWriter, r *http.Request) bool {
err := false
if route.method == "" {
return err
}
if route.method != r.Method {
err = true
w.WriteHeader(405)
w.Write([]byte("Unexpected request method: " + r.Method + ". Expected: " + route.method))
}
return err
}
func isAssetRequest(path string) bool {
res := false
//TODO add configurator
if strings.Contains(path, "/assets/css/") || strings.Contains(path, "/assets/js/") || strings.Contains(path, "/assets/fonts/") {
res = true
}
return res
}
func (router *Router) Handle(w http.ResponseWriter, r *http.Request) {
mutex.Lock()
defer mutex.Unlock()
route := router.match(r)
LOGGER.Println("Processing request: " + r.URL.Path)
// TODO this might be need rethinked
if route.CheckRequestMethod(w, r) {
return
}
obj, ok := LaunchController(route.controller)
if ok {
controllerValues := reflect.ValueOf(obj)
goninjaCtrlField := controllerValues.Elem().Field(0)
FullController := Controller{Request: r, Writer: w, Name: route.controller, Action: route.action}
goninjaCtrlField.Set(reflect.ValueOf(FullController))
action := controllerValues.MethodByName(route.action)
if !action.IsValid() {
w.WriteHeader(404)
w.Write([]byte("Action with name " + route.action + " wasn't found in controller " + route.controller))
} else {
res := action.Call([]reflect.Value{})[0]
result := res.Interface().(Response)
LOGGER.Println(action)
LOGGER.Println(result.Content)
}
} else if isAssetRequest(r.URL.Path) == true {
w.Header().Set("Content-Type", "text/css; charset=utf-8")
http.ServeFile(w, r, CURRENT_DIR+r.URL.Path)
} else {
route.ControllerNotFound(w, r)
}
}