Skip to content

Commit 29d4d6c

Browse files
authored
feat: added tree-based router (#48)
1 parent 3e5aec1 commit 29d4d6c

File tree

7 files changed

+637
-685
lines changed

7 files changed

+637
-685
lines changed

group_test.go

-5
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,6 @@ func TestGroup_Add(t *testing.T) {
100100
c.JSON(http.StatusCreated, Map{"message": c.Request().Method})
101101
}, []string{http.MethodGet, http.MethodPost})
102102

103-
assert.Equal(t, 1, len(k.router.routes))
104-
assert.Equal(t, 2, len(k.router.routes[0].methods))
105-
assert.Equal(t, 0, len(k.router.routes[0].middlewares))
106-
assert.Equal(t, []string{http.MethodGet, http.MethodPost}, k.router.routes[0].methods)
107-
108103
testCases := []struct {
109104
req *http.Request
110105
res *httptest.ResponseRecorder

kid.go

+16-17
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type (
2828
//
2929
// It's a framework instance.
3030
Kid struct {
31-
router Router
31+
router Tree
3232
middlewares []MiddlewareFunc
3333
notFoundHandler HandlerFunc
3434
methodNotAllowedHandler HandlerFunc
@@ -43,7 +43,7 @@ type (
4343
// Version of Kid.
4444
const Version string = "0.1.0"
4545

46-
// allMethods is all of the HTTP methods.
46+
// allMethods is a list of all HTTP methods.
4747
var allMethods = []string{
4848
http.MethodGet, http.MethodPost, http.MethodPut,
4949
http.MethodPatch, http.MethodDelete, http.MethodHead,
@@ -53,7 +53,7 @@ var allMethods = []string{
5353
// New returns a new instance of Kid.
5454
func New() *Kid {
5555
kid := Kid{
56-
router: newRouter(),
56+
router: newTree(),
5757
middlewares: make([]MiddlewareFunc, 0),
5858
notFoundHandler: defaultNotFoundHandler,
5959
methodNotAllowedHandler: defaultMethodNotAllowedHandler,
@@ -94,70 +94,70 @@ func (k *Kid) Use(middleware MiddlewareFunc) {
9494
//
9595
// Specifying middlewares is optional. Middlewares will only be applied to this route.
9696
func (k *Kid) Get(path string, handler HandlerFunc, middlewares ...MiddlewareFunc) {
97-
k.router.add(path, handler, []string{http.MethodGet}, middlewares)
97+
k.router.insertNode(path, []string{http.MethodGet}, middlewares, handler)
9898
}
9999

100100
// Post registers a new handler for the given path for POST method.
101101
//
102102
// Specifying middlewares is optional. Middlewares will only be applied to this route.
103103
func (k *Kid) Post(path string, handler HandlerFunc, middlewares ...MiddlewareFunc) {
104-
k.router.add(path, handler, []string{http.MethodPost}, middlewares)
104+
k.router.insertNode(path, []string{http.MethodPost}, middlewares, handler)
105105
}
106106

107107
// Put registers a new handler for the given path for PUT method.
108108
//
109109
// Specifying middlewares is optional. Middlewares will only be applied to this route.
110110
func (k *Kid) Put(path string, handler HandlerFunc, middlewares ...MiddlewareFunc) {
111-
k.router.add(path, handler, []string{http.MethodPut}, middlewares)
111+
k.router.insertNode(path, []string{http.MethodPut}, middlewares, handler)
112112
}
113113

114114
// Patch registers a new handler for the given path for PATCH method.
115115
//
116116
// Specifying middlewares is optional. Middlewares will only be applied to this route.
117117
func (k *Kid) Patch(path string, handler HandlerFunc, middlewares ...MiddlewareFunc) {
118-
k.router.add(path, handler, []string{http.MethodPatch}, middlewares)
118+
k.router.insertNode(path, []string{http.MethodPatch}, middlewares, handler)
119119
}
120120

121121
// Delete registers a new handler for the given path for DELETE method.
122122
//
123123
// Specifying middlewares is optional. Middlewares will only be applied to this route.
124124
func (k *Kid) Delete(path string, handler HandlerFunc, middlewares ...MiddlewareFunc) {
125-
k.router.add(path, handler, []string{http.MethodDelete}, middlewares)
125+
k.router.insertNode(path, []string{http.MethodDelete}, middlewares, handler)
126126
}
127127

128128
// Head registers a new handler for the given path for HEAD method.
129129
//
130130
// Specifying middlewares is optional. Middlewares will only be applied to this route.
131131
func (k *Kid) Head(path string, handler HandlerFunc, middlewares ...MiddlewareFunc) {
132-
k.router.add(path, handler, []string{http.MethodHead}, middlewares)
132+
k.router.insertNode(path, []string{http.MethodHead}, middlewares, handler)
133133
}
134134

135135
// Options registers a new handler for the given path for OPTIONS method.
136136
//
137137
// Specifying middlewares is optional. Middlewares will only be applied to this route.
138138
func (k *Kid) Options(path string, handler HandlerFunc, middlewares ...MiddlewareFunc) {
139-
k.router.add(path, handler, []string{http.MethodOptions}, middlewares)
139+
k.router.insertNode(path, []string{http.MethodOptions}, middlewares, handler)
140140
}
141141

142142
// Connect registers a new handler for the given path for CONNECT method.
143143
//
144144
// Specifying middlewares is optional. Middlewares will only be applied to this route.
145145
func (k *Kid) Connect(path string, handler HandlerFunc, middlewares ...MiddlewareFunc) {
146-
k.router.add(path, handler, []string{http.MethodConnect}, middlewares)
146+
k.router.insertNode(path, []string{http.MethodConnect}, middlewares, handler)
147147
}
148148

149149
// Trace registers a new handler for the given path for TRACE method.
150150
//
151151
// Specifying middlewares is optional. Middlewares will only be applied to this route.
152152
func (k *Kid) Trace(path string, handler HandlerFunc, middlewares ...MiddlewareFunc) {
153-
k.router.add(path, handler, []string{http.MethodTrace}, middlewares)
153+
k.router.insertNode(path, []string{http.MethodTrace}, middlewares, handler)
154154
}
155155

156156
// Any registers a new handler for the given path for all of the HTTP methods.
157157
//
158158
// Specifying middlewares is optional. Middlewares will only be applied to this route.
159159
func (k *Kid) Any(path string, handler HandlerFunc, middlewares ...MiddlewareFunc) {
160-
k.router.add(path, handler, allMethods, middlewares)
160+
k.router.insertNode(path, allMethods, middlewares, handler)
161161
}
162162

163163
// Group creates a new router group.
@@ -172,7 +172,7 @@ func (k *Kid) Group(prefix string, middlewares ...MiddlewareFunc) Group {
172172
//
173173
// Specifying middlewares is optional. Middlewares will only be applied to this route.
174174
func (k *Kid) Add(path string, handler HandlerFunc, methods []string, middlewares ...MiddlewareFunc) {
175-
k.router.add(path, handler, methods, middlewares)
175+
k.router.insertNode(path, methods, middlewares, handler)
176176
}
177177

178178
// Static registers a new route for serving static files.
@@ -188,18 +188,17 @@ func (k *Kid) Static(urlPath, staticRoot string, middlewares ...MiddlewareFunc)
188188
func (k *Kid) StaticFS(urlPath string, fs http.FileSystem, middlewares ...MiddlewareFunc) {
189189
fileServer := newFileServer(urlPath, fs)
190190

191-
methods := []string{http.MethodGet}
192191
path := appendSlash(urlPath) + "{*filePath}"
193192

194-
k.router.add(path, WrapHandler(fileServer), methods, middlewares)
193+
k.router.insertNode(path, []string{http.MethodGet}, middlewares, WrapHandler(fileServer))
195194
}
196195

197196
// ServeHTTP implements the http.HandlerFunc interface.
198197
func (k *Kid) ServeHTTP(w http.ResponseWriter, r *http.Request) {
199198
c := k.pool.Get().(*Context)
200199
c.reset(r, w)
201200

202-
route, params, err := k.router.find(getPath(r.URL), r.Method)
201+
route, params, err := k.router.search(getPath(r.URL), r.Method)
203202

204203
c.setParams(params)
205204

kid_test.go

+1-63
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func TestNew(t *testing.T) {
1818
k := New()
1919

2020
assert.NotNil(t, k)
21-
assert.Equal(t, newRouter(), k.router)
21+
assert.Equal(t, newTree(), k.router)
2222
assert.Equal(t, 0, len(k.middlewares))
2323
assert.Equal(t, serializer.NewJSONSerializer(), k.jsonSerializer)
2424
assert.Equal(t, serializer.NewXMLSerializer(), k.xmlSerializer)
@@ -57,11 +57,6 @@ func TestKid_Get(t *testing.T) {
5757
c.JSON(http.StatusOK, Map{"message": fmt.Sprintf("Hello %s", name)})
5858
})
5959

60-
assert.Equal(t, 2, len(k.router.routes))
61-
assert.Equal(t, 1, len(k.router.routes[0].methods))
62-
assert.Equal(t, 0, len(k.router.routes[0].middlewares))
63-
assert.Equal(t, http.MethodGet, k.router.routes[0].methods[0])
64-
6560
req := httptest.NewRequest(http.MethodGet, "/test", nil)
6661
res := httptest.NewRecorder()
6762

@@ -91,11 +86,6 @@ func TestKid_Post(t *testing.T) {
9186
c.JSON(http.StatusCreated, Map{"message": "ok"})
9287
})
9388

94-
assert.Equal(t, 1, len(k.router.routes))
95-
assert.Equal(t, 1, len(k.router.routes[0].methods))
96-
assert.Equal(t, 0, len(k.router.routes[0].middlewares))
97-
assert.Equal(t, http.MethodPost, k.router.routes[0].methods[0])
98-
9989
req := httptest.NewRequest(http.MethodPost, "/test", nil)
10090
res := httptest.NewRecorder()
10191

@@ -117,11 +107,6 @@ func TestKid_Put(t *testing.T) {
117107
c.JSON(http.StatusCreated, Map{"message": "put"})
118108
})
119109

120-
assert.Equal(t, 1, len(k.router.routes))
121-
assert.Equal(t, 1, len(k.router.routes[0].methods))
122-
assert.Equal(t, 0, len(k.router.routes[0].middlewares))
123-
assert.Equal(t, http.MethodPut, k.router.routes[0].methods[0])
124-
125110
req := httptest.NewRequest(http.MethodPut, "/test", nil)
126111
res := httptest.NewRecorder()
127112

@@ -143,11 +128,6 @@ func TestKid_Delete(t *testing.T) {
143128
c.JSON(http.StatusCreated, Map{"message": "deleted"})
144129
})
145130

146-
assert.Equal(t, 1, len(k.router.routes))
147-
assert.Equal(t, 1, len(k.router.routes[0].methods))
148-
assert.Equal(t, 0, len(k.router.routes[0].middlewares))
149-
assert.Equal(t, http.MethodDelete, k.router.routes[0].methods[0])
150-
151131
req := httptest.NewRequest(http.MethodDelete, "/test", nil)
152132
res := httptest.NewRecorder()
153133

@@ -169,11 +149,6 @@ func TestKid_Patch(t *testing.T) {
169149
c.JSON(http.StatusCreated, Map{"message": "patch"})
170150
})
171151

172-
assert.Equal(t, 1, len(k.router.routes))
173-
assert.Equal(t, 1, len(k.router.routes[0].methods))
174-
assert.Equal(t, 0, len(k.router.routes[0].middlewares))
175-
assert.Equal(t, http.MethodPatch, k.router.routes[0].methods[0])
176-
177152
req := httptest.NewRequest(http.MethodPatch, "/test", nil)
178153
res := httptest.NewRecorder()
179154

@@ -195,11 +170,6 @@ func TestKid_Trace(t *testing.T) {
195170
c.JSON(http.StatusCreated, Map{"message": "trace"})
196171
})
197172

198-
assert.Equal(t, 1, len(k.router.routes))
199-
assert.Equal(t, 1, len(k.router.routes[0].methods))
200-
assert.Equal(t, 0, len(k.router.routes[0].middlewares))
201-
assert.Equal(t, http.MethodTrace, k.router.routes[0].methods[0])
202-
203173
req := httptest.NewRequest(http.MethodTrace, "/test", nil)
204174
res := httptest.NewRecorder()
205175

@@ -221,11 +191,6 @@ func TestKid_Connect(t *testing.T) {
221191
c.JSON(http.StatusCreated, Map{"message": "connect"})
222192
})
223193

224-
assert.Equal(t, 1, len(k.router.routes))
225-
assert.Equal(t, 1, len(k.router.routes[0].methods))
226-
assert.Equal(t, 0, len(k.router.routes[0].middlewares))
227-
assert.Equal(t, http.MethodConnect, k.router.routes[0].methods[0])
228-
229194
req := httptest.NewRequest(http.MethodConnect, "/test", nil)
230195
res := httptest.NewRecorder()
231196

@@ -247,11 +212,6 @@ func TestKid_Options(t *testing.T) {
247212
c.JSON(http.StatusCreated, Map{"message": "options"})
248213
})
249214

250-
assert.Equal(t, 1, len(k.router.routes))
251-
assert.Equal(t, 1, len(k.router.routes[0].methods))
252-
assert.Equal(t, 0, len(k.router.routes[0].middlewares))
253-
assert.Equal(t, http.MethodOptions, k.router.routes[0].methods[0])
254-
255215
req := httptest.NewRequest(http.MethodOptions, "/test", nil)
256216
res := httptest.NewRecorder()
257217

@@ -273,11 +233,6 @@ func TestKid_Head(t *testing.T) {
273233
c.JSON(http.StatusCreated, Map{"message": "head"})
274234
})
275235

276-
assert.Equal(t, 1, len(k.router.routes))
277-
assert.Equal(t, 1, len(k.router.routes[0].methods))
278-
assert.Equal(t, 0, len(k.router.routes[0].middlewares))
279-
assert.Equal(t, http.MethodHead, k.router.routes[0].methods[0])
280-
281236
req := httptest.NewRequest(http.MethodHead, "/test", nil)
282237
res := httptest.NewRecorder()
283238

@@ -299,11 +254,6 @@ func TestKid_Add(t *testing.T) {
299254
c.JSON(http.StatusCreated, Map{"message": c.Request().Method})
300255
}, []string{http.MethodGet, http.MethodPost})
301256

302-
assert.Equal(t, 1, len(k.router.routes))
303-
assert.Equal(t, 2, len(k.router.routes[0].methods))
304-
assert.Equal(t, 0, len(k.router.routes[0].middlewares))
305-
assert.Equal(t, []string{http.MethodGet, http.MethodPost}, k.router.routes[0].methods)
306-
307257
testCases := []struct {
308258
req *http.Request
309259
res *httptest.ResponseRecorder
@@ -335,18 +285,6 @@ func TestKid_Any(t *testing.T) {
335285
c.JSON(http.StatusCreated, Map{"message": c.Request().Method})
336286
})
337287

338-
assert.Equal(t, 1, len(k.router.routes))
339-
assert.Equal(t, 9, len(k.router.routes[0].methods))
340-
assert.Equal(t, 0, len(k.router.routes[0].middlewares))
341-
assert.Equal(t,
342-
[]string{
343-
http.MethodGet, http.MethodPost, http.MethodPut,
344-
http.MethodPatch, http.MethodDelete, http.MethodHead,
345-
http.MethodOptions, http.MethodConnect, http.MethodTrace,
346-
},
347-
k.router.routes[0].methods,
348-
)
349-
350288
testCases := []struct {
351289
req *http.Request
352290
res *httptest.ResponseRecorder

0 commit comments

Comments
 (0)