From d105270d58157b18d45ca7d80158c1243f92f83a Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Tue, 23 Feb 2016 16:27:55 -0800 Subject: [PATCH] Fixed Router#Find #217 Signed-off-by: Vishal Rana --- router.go | 42 ++++++++++++++++++--------------- router_test.go | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 19 deletions(-) diff --git a/router.go b/router.go index 42a05663..b0bbed20 100644 --- a/router.go +++ b/router.go @@ -43,7 +43,7 @@ type ( const ( skind kind = iota pkind - mkind + akind ) // NewRouter returns a new Router instance. @@ -82,7 +82,7 @@ func (r *Router) Add(method, path string, h HandlerFunc, e *Echo) { } else if path[i] == '*' { r.insert(method, path[:i], nil, skind, "", nil, e) pnames = append(pnames, "_*") - r.insert(method, path[:i+1], h, mkind, ppath, pnames, e) + r.insert(method, path[:i+1], h, akind, ppath, pnames, e) return } } @@ -286,6 +286,7 @@ func (n *node) check405() HandlerFunc { // Find dispatches the request to the handler whos route is matched with the // specified request path. func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo) { + // r.tree.printTree("", true) h = notFoundHandler e = r.echo cn := r.tree // Current node as root @@ -299,7 +300,7 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo ns string // Next search ) - // Search order static > param > match-any + // Search order static > param > any for { if search == "" { goto End @@ -329,12 +330,11 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo search = ns if nk == pkind { goto Param - } else if nk == mkind { - goto MatchAny - } else { - // Not found - return + } else if nk == akind { + goto Any } + // Not found + return } if search == "" { @@ -342,8 +342,7 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo } // Static node - c = cn.findChild(search[0], skind) - if c != nil { + if c = cn.findChild(search[0], skind); c != nil { // Save next if cn.label == '/' { nk = pkind @@ -356,11 +355,10 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo // Param node Param: - c = cn.findChildByKind(pkind) - if c != nil { + if c = cn.findChildByKind(pkind); c != nil { // Save next if cn.label == '/' { - nk = mkind + nk = akind nn = cn ns = search } @@ -374,10 +372,16 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo continue } - // Match-any node - MatchAny: - // c = cn.getChild() - if cn = cn.findChildByKind(mkind); cn == nil { + // Any node + Any: + if cn = cn.findChildByKind(akind); cn == nil { + cn = nn + search = ns + if nk == pkind { + goto Param + } else if nk == akind { + goto Any + } // Not found return } @@ -397,9 +401,9 @@ End: if h == nil { h = cn.check405() - // Dig further for match-any, might have an empty value for *, e.g. + // Dig further for any, might have an empty value for *, e.g. // serving a directory. Issue #207. - if cn = cn.findChildByKind(mkind); cn == nil { + if cn = cn.findChildByKind(akind); cn == nil { return } ctx.pvalues[len(cn.pnames)-1] = "" diff --git a/router_test.go b/router_test.go index c3357223..c0ffc6b6 100644 --- a/router_test.go +++ b/router_test.go @@ -503,6 +503,70 @@ func TestRouterPriority(t *testing.T) { } } +// Issue #217 +func TestRouterPriorityNext(t *testing.T) { + e := New() + r := e.router + + // Routes + r.Add(GET, "/aa", func(c *Context) error { + c.Set("a", 1) + return nil + }, e) + r.Add(GET, "/ab", func(c *Context) error { + c.Set("b", 2) + return nil + }, e) + r.Add(GET, "/abc", func(c *Context) error { + c.Set("c", 3) + return nil + }, e) + r.Add(GET, "/abd", func(c *Context) error { + c.Set("d", 4) + return nil + }, e) + r.Add(GET, "/*", func(c *Context) error { + c.Set("e", 5) + return nil + }, e) + c := NewContext(nil, nil, e) + + // Route > /aa + h, _ := r.Find(GET, "/aa", c) + if assert.NotNil(t, h) { + h(c) + assert.Equal(t, 1, c.Get("a")) + } + + // Route > /ab + h, _ = r.Find(GET, "/ab", c) + if assert.NotNil(t, h) { + h(c) + assert.Equal(t, 2, c.Get("b")) + } + + // Route > /abc + h, _ = r.Find(GET, "/abc", c) + if assert.NotNil(t, h) { + h(c) + assert.Equal(t, 3, c.Get("c")) + } + + // Route > /abd + h, _ = r.Find(GET, "/abd", c) + if assert.NotNil(t, h) { + h(c) + assert.Equal(t, 4, c.Get("d")) + } + + // Route > /* + h, _ = r.Find(GET, "/abc.html", c) + if assert.NotNil(t, h) { + h(c) + assert.Equal(t, 5, c.Get("e")) + } +} + func TestRouterParamNames(t *testing.T) { e := New() r := e.router