Skip to content

Commit dcba8b2

Browse files
author
AnikHasibul
committed
🐛 FIX: multiple router group chaining bug
1 parent 86281a4 commit dcba8b2

File tree

2 files changed

+63
-7
lines changed

2 files changed

+63
-7
lines changed

router.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ var (
9191
// Router is a http.Handler which can be used to dispatch requests to different
9292
// handler functions via configurable routes
9393
type Router struct {
94+
parent *Router
9495
beginPath string
9596
trees map[string]*node
9697

@@ -159,13 +160,13 @@ func New() *Router {
159160
// Path auto-correction, including trailing slashes, is enabled by default.
160161
func (r *Router) Group(path string) *Router {
161162
g := &Router{
163+
parent: r,
162164
beginPath: path,
163165
RedirectTrailingSlash: true,
164166
RedirectFixedPath: true,
165167
HandleMethodNotAllowed: true,
166168
HandleOPTIONS: true,
167169
}
168-
r.NotFound = g.Handler
169170
return g
170171
}
171172

@@ -219,14 +220,20 @@ func (r *Router) Handle(method, path string, handle fasthttp.RequestHandler) {
219220
if r.beginPath != "/" {
220221
path = r.beginPath + path
221222
}
222-
if r.trees == nil {
223-
r.trees = make(map[string]*node)
223+
var route *Router
224+
if r.parent != nil {
225+
route = r.parent
226+
} else {
227+
route = r
228+
}
229+
if route.trees == nil {
230+
route.trees = make(map[string]*node)
224231
}
225232

226-
root := r.trees[method]
233+
root := route.trees[method]
227234
if root == nil {
228235
root = new(node)
229-
r.trees[method] = root
236+
route.trees[method] = root
230237
}
231238

232239
root.addRoute(path, handle)

router_test.go

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ func TestRouterChaining(t *testing.T) {
312312
func TestRouterGroup(t *testing.T) {
313313
r1 := New()
314314
r2 := r1.Group("/boo")
315+
r3 := r1.Group("/goo")
316+
r4 := r1.Group("/moo")
315317
fooHit := false
316318
r1.POST("/foo", func(ctx *fasthttp.RequestCtx) {
317319
fooHit = true
@@ -323,7 +325,14 @@ func TestRouterGroup(t *testing.T) {
323325
barHit = true
324326
ctx.SetStatusCode(fasthttp.StatusOK)
325327
})
326-
328+
r3.POST("/bar", func(ctx *fasthttp.RequestCtx) {
329+
barHit = true
330+
ctx.SetStatusCode(fasthttp.StatusOK)
331+
})
332+
r4.POST("/bar", func(ctx *fasthttp.RequestCtx) {
333+
barHit = true
334+
ctx.SetStatusCode(fasthttp.StatusOK)
335+
})
327336
s := &fasthttp.Server{
328337
Handler: r1.Handler,
329338
}
@@ -369,7 +378,47 @@ func TestRouterGroup(t *testing.T) {
369378
t.Fatalf("Unexpected error when reading response: %s", err)
370379
}
371380
if !(resp.Header.StatusCode() == fasthttp.StatusOK && barHit) {
372-
t.Errorf("Chained routing failed with router chaining.")
381+
t.Errorf("Chained routing failed with router grouping.")
382+
t.FailNow()
383+
}
384+
385+
rw.r.WriteString("POST /goo/bar HTTP/1.1\r\n\r\n")
386+
go func() {
387+
ch <- s.ServeConn(rw)
388+
}()
389+
select {
390+
case err := <-ch:
391+
if err != nil {
392+
t.Fatalf("return error %s", err)
393+
}
394+
case <-time.After(100 * time.Millisecond):
395+
t.Fatalf("timeout")
396+
}
397+
if err := resp.Read(br); err != nil {
398+
t.Fatalf("Unexpected error when reading response: %s", err)
399+
}
400+
if !(resp.Header.StatusCode() == fasthttp.StatusOK && barHit) {
401+
t.Errorf("Chained routing failed with router grouping.")
402+
t.FailNow()
403+
}
404+
405+
rw.r.WriteString("POST /moo/bar HTTP/1.1\r\n\r\n")
406+
go func() {
407+
ch <- s.ServeConn(rw)
408+
}()
409+
select {
410+
case err := <-ch:
411+
if err != nil {
412+
t.Fatalf("return error %s", err)
413+
}
414+
case <-time.After(100 * time.Millisecond):
415+
t.Fatalf("timeout")
416+
}
417+
if err := resp.Read(br); err != nil {
418+
t.Fatalf("Unexpected error when reading response: %s", err)
419+
}
420+
if !(resp.Header.StatusCode() == fasthttp.StatusOK && barHit) {
421+
t.Errorf("Chained routing failed with router grouping.")
373422
t.FailNow()
374423
}
375424

0 commit comments

Comments
 (0)