-
Notifications
You must be signed in to change notification settings - Fork 0
/
engine.go
149 lines (121 loc) · 3.07 KB
/
engine.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
package rum
import (
"net/http"
"sync"
)
var once sync.Once
var internalEngine *Engine
var maxParams = 20
// HandlerFunc defines the handler used by gin middleware as return value.
type HandlerFunc func(*Context)
// HandlersChain defines a HandlerFunc slice.
type HandlersChain []HandlerFunc
type methodTree struct {
method string
root *node
}
type trees []methodTree
func (trees trees) get(method string) *node {
for _, tree := range trees {
if tree.method == method {
return tree.root
}
}
return nil
}
type Engine struct {
addr string
trees
group *RouterGroup
pool sync.Pool
}
func (engine *Engine) allocateContext() *Context {
v := make(Params, 0, maxParams)
return &Context{Params: v, index: -1}
}
func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c := e.pool.Get().(*Context)
c.reset(w, r)
e.handle(c)
e.pool.Put(c)
}
func (e *Engine) addRoute(method, path string, handlers HandlersChain) {
assert1(path[0] == '/', "path must begin with '/'")
assert1(method != "", "HTTP method can not be empty")
assert1(len(handlers) > 0, "there must be at least one handler")
root := e.trees.get(method)
if root == nil {
root = new(node)
e.trees = append(e.trees, methodTree{method: method, root: root})
}
root.addRoute(path, handlers)
}
func (e *Engine) Use(middleware ...HandlerFunc) IRoutes {
return e.group.Use(middleware...)
}
func (e *Engine) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup {
return e.group.Group(relativePath, handlers...)
}
func (e *Engine) GET(path string, handlers ...HandlerFunc) IRoutes {
return e.group.GET(path, handlers...)
}
func (e *Engine) POST(path string, handlers ...HandlerFunc) IRoutes {
return e.group.POST(path, handlers...)
}
func (e *Engine) DELETE(path string, handlers ...HandlerFunc) IRoutes {
return e.group.DELETE(path, handlers...)
}
func (e *Engine) PUT(path string, handlers ...HandlerFunc) IRoutes {
return e.group.PUT(path, handlers...)
}
func (e *Engine) HEAD(path string, handlers ...HandlerFunc) IRoutes {
return e.group.HEAD(path, handlers...)
}
func (e *Engine) Handle(method, path string, handlers ...HandlerFunc) IRoutes {
return e.group.Handle(method, path, handlers...)
}
func New(addr string) *Engine {
engine := &Engine{
addr: addr,
trees: make(trees, 0),
group: &RouterGroup{
BasePath: "/",
root: true,
},
}
engine.group.engine = engine
engine.pool.New = func() interface{} {
return engine.allocateContext()
}
return engine
}
// Default returns an Engine instance with the middleware
func Default() *Engine {
once.Do(func() {
internalEngine = New(":9678")
})
return internalEngine
}
func (e *Engine) Start() {
http.ListenAndServe(e.addr, e)
}
func (e *Engine) handle(c *Context) {
tree := e.trees.get(c.Method)
if tree == nil {
NotFound(c)
return
}
handlers, params := tree.getValue(c.Path, &c.Params)
c.HandlersChain = handlers
if params != nil {
c.Params = *params
}
if c.HandlersChain == nil {
NotFound(c)
} else {
c.Next()
}
}
func NotFound(c *Context) {
c.String(http.StatusNotFound, "404 NOT FOUND: %s\n", c.Path)
}