From a9df83037d950bf9ea442806501047eaa2b0f00e Mon Sep 17 00:00:00 2001 From: stffabi Date: Sun, 3 Jan 2021 19:35:00 +0100 Subject: [PATCH] Do not handle special trailing slash case for partial prefix (#1741) * Add tests for issue #1739 * Handle special trailing slash case only for a matching prefix Only handle the special trailing slash case if the whole prefix matches to avoid matching a wrong route for overlapping prefixes, e.g. /users/* for the path /users_prefix/ where the route is only a partial prefix of the requested path. --- router.go | 8 ++++---- router_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/router.go b/router.go index 749dbf4f6..5010659a6 100644 --- a/router.go +++ b/router.go @@ -372,14 +372,14 @@ func (r *Router) Find(method, path string, c Context) { if search == "" && (nn == nil || cn.parent == nil || cn.ppath != "") { break } + // Handle special case of trailing slash route with existing any route (see #1526) + if search == "" && path[len(path)-1] == '/' && cn.anyChildren != nil { + goto Any + } } // Attempt to go back up the tree on no matching prefix or no remaining search if l != pl || search == "" { - // Handle special case of trailing slash route with existing any route (see #1526) - if path[len(path)-1] == '/' && cn.anyChildren != nil { - goto Any - } if nn == nil { // Issue #1348 return // Not found } diff --git a/router_test.go b/router_test.go index aafc622cb..a5e53c05b 100644 --- a/router_test.go +++ b/router_test.go @@ -750,6 +750,47 @@ func TestRouterMatchAny(t *testing.T) { assert.Equal(t, "joe", c.Param("*")) } +// Issue #1739 +func TestRouterMatchAnyPrefixIssue(t *testing.T) { + e := New() + r := e.router + + // Routes + r.Add(http.MethodGet, "/*", func(c Context) error { + c.Set("path", c.Path()) + return nil + }) + r.Add(http.MethodGet, "/users/*", func(c Context) error { + c.Set("path", c.Path()) + return nil + }) + c := e.NewContext(nil, nil).(*context) + r.Find(http.MethodGet, "/", c) + c.handler(c) + assert.Equal(t, "/*", c.Get("path")) + assert.Equal(t, "", c.Param("*")) + + r.Find(http.MethodGet, "/users", c) + c.handler(c) + assert.Equal(t, "/*", c.Get("path")) + assert.Equal(t, "users", c.Param("*")) + + r.Find(http.MethodGet, "/users/", c) + c.handler(c) + assert.Equal(t, "/users/*", c.Get("path")) + assert.Equal(t, "", c.Param("*")) + + r.Find(http.MethodGet, "/users_prefix", c) + c.handler(c) + assert.Equal(t, "/*", c.Get("path")) + assert.Equal(t, "users_prefix", c.Param("*")) + + r.Find(http.MethodGet, "/users_prefix/", c) + c.handler(c) + assert.Equal(t, "/*", c.Get("path")) + assert.Equal(t, "users_prefix/", c.Param("*")) +} + // TestRouterMatchAnySlash shall verify finding the best route // for any routes with trailing slash requests func TestRouterMatchAnySlash(t *testing.T) {