-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
router.go
138 lines (111 loc) · 3.94 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
package http
import (
"github.com/firmeve/firmeve/context"
"github.com/firmeve/firmeve/kernel/contract"
"github.com/julienschmidt/httprouter"
"net/http"
"strings"
)
type Router struct {
Application contract.Application
router *httprouter.Router
routes map[string]contract.HttpRoute
routeKeys []string
event contract.Event
logger contract.Loggable
}
func New(app contract.Application) contract.HttpRouter {
return &Router{
Application: app,
router: httprouter.New(),
routes: make(map[string]contract.HttpRoute, 0),
routeKeys: make([]string, 0),
event: app.Resolve(`event`).(contract.Event),
logger: app.Resolve(`logger`).(contract.Loggable),
}
}
func (r *Router) GET(path string, handler contract.ContextHandler) contract.HttpRoute {
return r.createRoute(http.MethodGet, path, handler)
}
func (r *Router) POST(path string, handler contract.ContextHandler) contract.HttpRoute {
return r.createRoute(http.MethodPost, path, handler)
}
func (r *Router) PUT(path string, handler contract.ContextHandler) contract.HttpRoute {
return r.createRoute(http.MethodPut, path, handler)
}
func (r *Router) PATCH(path string, handler contract.ContextHandler) contract.HttpRoute {
return r.createRoute(http.MethodPatch, path, handler)
}
func (r *Router) DELETE(path string, handler contract.ContextHandler) contract.HttpRoute {
return r.createRoute(http.MethodDelete, path, handler)
}
func (r *Router) OPTIONS(path string, handler contract.ContextHandler) contract.HttpRoute {
return r.createRoute(http.MethodOptions, path, handler)
}
// serve static files
func (r *Router) Static(path string, root string) contract.HttpRouter {
r.router.ServeFiles(strings.Join([]string{path, `/*filepath`}, ``), http.Dir(root))
return r
}
func (r *Router) NotFound(handler contract.ContextHandler) contract.HttpRouter {
r.router.NotFound = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
context.NewContext(r.Application, NewHttp(r.Application, req, w.(contract.HttpWrapResponseWriter)), handler).Next()
})
return r
}
func (r *Router) Handler(method, path string, handler http.HandlerFunc) {
r.createRoute(method, path, func(c contract.Context) {
protocol := c.Protocol().(contract.HttpProtocol)
handler(protocol.ResponseWriter(), protocol.Request())
c.Next()
})
}
func (r *Router) HttpRouter() *httprouter.Router {
return r.router
}
//
func (r *Router) Group(prefix string) contract.HttpRouteGroup {
return newGroup(r).Prefix(prefix)
}
func (r *Router) createRoute(method string, path string, handler contract.ContextHandler) contract.HttpRoute {
key := r.routeKey(method, path)
r.routes[key] = newRoute(path, handler)
r.router.Handle(method, path, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
// base http
currentHttp := NewHttp(r.Application, req, w.(contract.HttpWrapResponseWriter))
currentHttp.SetParams(params)
currentHttp.SetRoute(r.routes[key])
// context create
ctx := context.NewContext(r.Application, currentHttp, r.routes[key].Handlers()...)
// router match dispatch
r.event.Dispatch(`http.route.matched`, ctx, r.routes[key])
ctx.Next()
releaseHttp(r.Application, currentHttp)
context.ReleaseContext(r.Application, ctx)
})
return r.routes[key]
}
func (r *Router) routeKey(method, path string) string {
return strings.Join([]string{method, path}, `.`)
}
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// wrap record statusCode
wrap := NewWrapResponseWriter(w)
// dispatch router
r.event.Dispatch(`http.request`, map[string]interface{}{
`request`: req,
`response`: wrap,
})
r.router.ServeHTTP(wrap, req)
//// record start time
//startTime := time2.Now()
//// request log
//r.logger.Debug(``,
// `Method`, req.Method,
// `StatusCode`, wrap.StatusCode(),
// `URI`, req.RequestURI,
// `IPAddress`, http2.ClientIP(req),
// `Agent`, req.Header.Get(`user-agent`),
// `ExecuteTime`, time2.Now().Sub(startTime),
//)
}