Skip to content

Commit ccf6f1a

Browse files
committed
refs #1412: Fix parent nodes for route insert on node split
1 parent 616db6d commit ccf6f1a

File tree

2 files changed

+148
-54
lines changed

2 files changed

+148
-54
lines changed

router.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string
136136
// Split node
137137
n := newNode(cn.kind, cn.prefix[l:], cn, cn.children, cn.methodHandler, cn.ppath, cn.pnames)
138138

139+
// Update parent path for all children to new node
140+
for _, child := range cn.children {
141+
child.parent = n
142+
}
143+
139144
// Reset parent node
140145
cn.kind = skind
141146
cn.label = cn.prefix[0]
@@ -417,6 +422,10 @@ func (r *Router) Find(method, path string, c Context) {
417422
if np == nil {
418423
break // no further parent nodes in tree, abort
419424
}
425+
var str strings.Builder
426+
str.WriteString(nn.prefix)
427+
str.WriteString(search)
428+
search = str.String()
420429
nn = np
421430
}
422431
if cn != nil { // use the found "any" route and update path

router_test.go

Lines changed: 139 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,15 @@ var (
499499
{"GET", "/people/:userId/moments/:collection", ""},
500500
{"DELETE", "/moments/:id", ""},
501501
}
502+
503+
// handlerHelper created a function that will set a context key for assertion
504+
handlerHelper = func(key string, value int) func(c Context) error {
505+
return func(c Context) error {
506+
c.Set(key, value)
507+
c.Set("path", c.Path())
508+
return nil
509+
}
510+
}
502511
)
503512

504513
func TestRouterStatic(t *testing.T) {
@@ -631,6 +640,56 @@ func TestRouterMatchAnyMultiLevel(t *testing.T) {
631640
assert.Equal(t, "/*", c.Get("path"))
632641
assert.Equal(t, "noapi/users/jim", c.Param("*"))
633642
}
643+
func TestRouterMatchAnyMultiLevelWithPost(t *testing.T) {
644+
e := New()
645+
r := e.router
646+
handler := func(c Context) error {
647+
c.Set("path", c.Path())
648+
return nil
649+
}
650+
651+
// Routes
652+
e.POST("/api/auth/login", handler)
653+
e.POST("/api/auth/forgotPassword", handler)
654+
e.Any("/api/*", handler)
655+
e.Any("/*", handler)
656+
657+
// POST /api/auth/login shall choose login method
658+
c := e.NewContext(nil, nil).(*context)
659+
r.Find(http.MethodPost, "/api/auth/login", c)
660+
c.handler(c)
661+
assert.Equal(t, "/api/auth/login", c.Get("path"))
662+
assert.Equal(t, "", c.Param("*"))
663+
664+
// GET /api/auth/login shall choose any route
665+
// c = e.NewContext(nil, nil).(*context)
666+
// r.Find(http.MethodGet, "/api/auth/login", c)
667+
// c.handler(c)
668+
// assert.Equal(t, "/api/*", c.Get("path"))
669+
// assert.Equal(t, "auth/login", c.Param("*"))
670+
671+
// POST /api/auth/logout shall choose nearest any route
672+
c = e.NewContext(nil, nil).(*context)
673+
r.Find(http.MethodPost, "/api/auth/logout", c)
674+
c.handler(c)
675+
assert.Equal(t, "/api/*", c.Get("path"))
676+
assert.Equal(t, "auth/logout", c.Param("*"))
677+
678+
// POST to /api/other/test shall choose nearest any route
679+
c = e.NewContext(nil, nil).(*context)
680+
r.Find(http.MethodPost, "/api/other/test", c)
681+
c.handler(c)
682+
assert.Equal(t, "/api/*", c.Get("path"))
683+
assert.Equal(t, "other/test", c.Param("*"))
684+
685+
// GET to /api/other/test shall choose nearest any route
686+
c = e.NewContext(nil, nil).(*context)
687+
r.Find(http.MethodGet, "/api/other/test", c)
688+
c.handler(c)
689+
assert.Equal(t, "/api/*", c.Get("path"))
690+
assert.Equal(t, "other/test", c.Param("*"))
691+
692+
}
634693

635694
func TestRouterMicroParam(t *testing.T) {
636695
e := New()
@@ -695,114 +754,117 @@ func TestRouterPriority(t *testing.T) {
695754
r := e.router
696755

697756
// Routes
698-
r.Add(http.MethodGet, "/users", func(c Context) error {
699-
c.Set("a", 1)
700-
return nil
701-
})
702-
r.Add(http.MethodGet, "/users/new", func(c Context) error {
703-
c.Set("b", 2)
704-
return nil
705-
})
706-
r.Add(http.MethodGet, "/users/:id", func(c Context) error {
707-
c.Set("c", 3)
708-
return nil
709-
})
710-
r.Add(http.MethodGet, "/users/dew", func(c Context) error {
711-
c.Set("d", 4)
712-
return nil
713-
})
714-
r.Add(http.MethodGet, "/users/:id/files", func(c Context) error {
715-
c.Set("e", 5)
716-
return nil
717-
})
718-
r.Add(http.MethodGet, "/users/newsee", func(c Context) error {
719-
c.Set("f", 6)
720-
return nil
721-
})
722-
r.Add(http.MethodGet, "/users/*", func(c Context) error {
723-
c.Set("g", 7)
724-
return nil
725-
})
726-
r.Add(http.MethodGet, "/users/new/*", func(c Context) error {
727-
c.Set("h", 8)
728-
return nil
729-
})
730-
r.Add(http.MethodGet, "/*", func(c Context) error {
731-
c.Set("i", 9)
732-
return nil
733-
})
734-
735-
c := e.NewContext(nil, nil).(*context)
757+
r.Add(http.MethodGet, "/users", handlerHelper("a", 1))
758+
r.Add(http.MethodGet, "/users/new", handlerHelper("b", 2))
759+
r.Add(http.MethodGet, "/users/:id", handlerHelper("c", 3))
760+
r.Add(http.MethodGet, "/users/dew", handlerHelper("d", 4))
761+
r.Add(http.MethodGet, "/users/:id/files", handlerHelper("e", 5))
762+
r.Add(http.MethodGet, "/users/newsee", handlerHelper("f", 6))
763+
r.Add(http.MethodGet, "/users/*", handlerHelper("g", 7))
764+
r.Add(http.MethodGet, "/users/new/*", handlerHelper("h", 8))
765+
r.Add(http.MethodGet, "/*", handlerHelper("i", 9))
736766

737767
// Route > /users
768+
c := e.NewContext(nil, nil).(*context)
738769
r.Find(http.MethodGet, "/users", c)
739770
c.handler(c)
740771
assert.Equal(t, 1, c.Get("a"))
772+
assert.Equal(t, "/users", c.Get("path"))
741773

742774
// Route > /users/new
775+
c = e.NewContext(nil, nil).(*context)
743776
r.Find(http.MethodGet, "/users/new", c)
744777
c.handler(c)
745778
assert.Equal(t, 2, c.Get("b"))
779+
assert.Equal(t, "/users/new", c.Get("path"))
746780

747781
// Route > /users/:id
782+
c = e.NewContext(nil, nil).(*context)
748783
r.Find(http.MethodGet, "/users/1", c)
749784
c.handler(c)
750785
assert.Equal(t, 3, c.Get("c"))
786+
assert.Equal(t, "/users/:id", c.Get("path"))
751787

752788
// Route > /users/dew
789+
c = e.NewContext(nil, nil).(*context)
753790
r.Find(http.MethodGet, "/users/dew", c)
754791
c.handler(c)
755792
assert.Equal(t, 4, c.Get("d"))
793+
assert.Equal(t, "/users/dew", c.Get("path"))
756794

757795
// Route > /users/:id/files
796+
c = e.NewContext(nil, nil).(*context)
758797
r.Find(http.MethodGet, "/users/1/files", c)
759798
c.handler(c)
760799
assert.Equal(t, 5, c.Get("e"))
800+
assert.Equal(t, "/users/:id/files", c.Get("path"))
761801

762802
// Route > /users/:id
803+
c = e.NewContext(nil, nil).(*context)
763804
r.Find(http.MethodGet, "/users/news", c)
764805
c.handler(c)
765806
assert.Equal(t, 3, c.Get("c"))
807+
assert.Equal(t, "/users/:id", c.Get("path"))
808+
809+
// Route > /users/newsee
810+
c = e.NewContext(nil, nil).(*context)
811+
r.Find(http.MethodGet, "/users/newsee", c)
812+
c.handler(c)
813+
assert.Equal(t, 6, c.Get("f"))
814+
assert.Equal(t, "/users/newsee", c.Get("path"))
766815

767816
// Route > /users/newsee
768817
r.Find(http.MethodGet, "/users/newsee", c)
769818
c.handler(c)
770819
assert.Equal(t, 6, c.Get("f"))
771820

772821
// Route > /users/*
822+
c = e.NewContext(nil, nil).(*context)
773823
r.Find(http.MethodGet, "/users/joe/books", c)
774824
c.handler(c)
775825
assert.Equal(t, 7, c.Get("g"))
826+
assert.Equal(t, "/users/*", c.Get("path"))
776827
assert.Equal(t, "joe/books", c.Param("*"))
777828

778829
// Route > /users/new/* should be matched
830+
c = e.NewContext(nil, nil).(*context)
779831
r.Find(http.MethodGet, "/users/new/someone", c)
780832
c.handler(c)
781833
assert.Equal(t, 8, c.Get("h"))
834+
assert.Equal(t, "/users/new/*", c.Get("path"))
782835
assert.Equal(t, "someone", c.Param("*"))
783836

784837
// Route > /users/* should be matched although /users/dew exists
838+
c = e.NewContext(nil, nil).(*context)
785839
r.Find(http.MethodGet, "/users/dew/someone", c)
786840
c.handler(c)
787841
assert.Equal(t, 7, c.Get("g"))
842+
assert.Equal(t, "/users/*", c.Get("path"))
843+
788844
assert.Equal(t, "dew/someone", c.Param("*"))
789845

790846
// Route > /users/* should be matched although /users/dew exists
791-
r.Find(http.MethodGet, "/users/notexists/someone/else", c)
847+
c = e.NewContext(nil, nil).(*context)
848+
r.Find(http.MethodGet, "/users/notexists/someone", c)
792849
c.handler(c)
793850
assert.Equal(t, 7, c.Get("g"))
794-
assert.Equal(t, "notexists/someone/else", c.Param("*"))
851+
assert.Equal(t, "/users/*", c.Get("path"))
852+
assert.Equal(t, "notexists/someone", c.Param("*"))
795853

796854
// Route > *
855+
c = e.NewContext(nil, nil).(*context)
797856
r.Find(http.MethodGet, "/nousers", c)
798857
c.handler(c)
799858
assert.Equal(t, 9, c.Get("i"))
859+
assert.Equal(t, "/*", c.Get("path"))
800860
assert.Equal(t, "nousers", c.Param("*"))
801861

802862
// Route > *
863+
c = e.NewContext(nil, nil).(*context)
803864
r.Find(http.MethodGet, "/nousers/new", c)
804865
c.handler(c)
805866
assert.Equal(t, 9, c.Get("i"))
867+
assert.Equal(t, "/*", c.Get("path"))
806868
assert.Equal(t, "nousers/new", c.Param("*"))
807869
}
808870

@@ -884,36 +946,59 @@ func TestRouterParamNames(t *testing.T) {
884946
assert.Equal(t, "1", c.Param("fid"))
885947
}
886948

887-
// Issue #623
949+
// Issue #623 and #1406
888950
func TestRouterStaticDynamicConflict(t *testing.T) {
889951
e := New()
890952
r := e.router
891-
c := e.NewContext(nil, nil)
892953

893-
r.Add(http.MethodGet, "/dictionary/skills", func(c Context) error {
894-
c.Set("a", 1)
895-
return nil
896-
})
897-
r.Add(http.MethodGet, "/dictionary/:name", func(c Context) error {
898-
c.Set("b", 2)
899-
return nil
900-
})
901-
r.Add(http.MethodGet, "/server", func(c Context) error {
902-
c.Set("c", 3)
903-
return nil
904-
})
954+
r.Add(http.MethodGet, "/dictionary/skills", handlerHelper("a", 1))
955+
r.Add(http.MethodGet, "/dictionary/:name", handlerHelper("b", 2))
956+
r.Add(http.MethodGet, "/users/new", handlerHelper("d", 4))
957+
r.Add(http.MethodGet, "/users/:name", handlerHelper("e", 5))
958+
r.Add(http.MethodGet, "/server", handlerHelper("c", 3))
959+
r.Add(http.MethodGet, "/", handlerHelper("f", 6))
905960

961+
c := e.NewContext(nil, nil)
906962
r.Find(http.MethodGet, "/dictionary/skills", c)
907963
c.Handler()(c)
908964
assert.Equal(t, 1, c.Get("a"))
965+
assert.Equal(t, "/dictionary/skills", c.Get("path"))
966+
967+
c = e.NewContext(nil, nil)
968+
r.Find(http.MethodGet, "/dictionary/skillsnot", c)
969+
c.Handler()(c)
970+
assert.Equal(t, 2, c.Get("b"))
971+
assert.Equal(t, "/dictionary/:name", c.Get("path"))
972+
909973
c = e.NewContext(nil, nil)
910974
r.Find(http.MethodGet, "/dictionary/type", c)
911975
c.Handler()(c)
912976
assert.Equal(t, 2, c.Get("b"))
977+
assert.Equal(t, "/dictionary/:name", c.Get("path"))
978+
913979
c = e.NewContext(nil, nil)
914980
r.Find(http.MethodGet, "/server", c)
915981
c.Handler()(c)
916982
assert.Equal(t, 3, c.Get("c"))
983+
assert.Equal(t, "/server", c.Get("path"))
984+
985+
c = e.NewContext(nil, nil)
986+
r.Find(http.MethodGet, "/users/new", c)
987+
c.Handler()(c)
988+
assert.Equal(t, 4, c.Get("d"))
989+
assert.Equal(t, "/users/new", c.Get("path"))
990+
991+
c = e.NewContext(nil, nil)
992+
r.Find(http.MethodGet, "/users/new2", c)
993+
c.Handler()(c)
994+
assert.Equal(t, 5, c.Get("e"))
995+
assert.Equal(t, "/users/:name", c.Get("path"))
996+
997+
c = e.NewContext(nil, nil)
998+
r.Find(http.MethodGet, "/", c)
999+
c.Handler()(c)
1000+
assert.Equal(t, 6, c.Get("f"))
1001+
assert.Equal(t, "/", c.Get("path"))
9171002
}
9181003

9191004
// Issue #1348

0 commit comments

Comments
 (0)