Skip to content

Commit

Permalink
Fix Mux.Find not correctly handling nested routes (#954)
Browse files Browse the repository at this point in the history
* Fix Mux.Find not correctly handling nested routes

* Add more test cases for TextMuxFind

* Fix Mux.Find returning partial path for failing cases
  • Loading branch information
joeriddles authored Sep 26, 2024
1 parent 882c15e commit 6ceb498
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 11 deletions.
21 changes: 14 additions & 7 deletions mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,18 +378,25 @@ func (mx *Mux) Find(rctx *Context, method, path string) string {
}

node, _, _ := mx.tree.FindRoute(rctx, m, path)
pattern := rctx.routePattern

if node != nil {
if node.subroutes == nil {
e := node.endpoints[m]
return e.pattern
}

if node != nil && node.subroutes != nil {
rctx.RoutePath = mx.nextRoutePath(rctx)
return node.subroutes.Find(rctx, method, rctx.RoutePath)
}
subPattern := node.subroutes.Find(rctx, method, rctx.RoutePath)
if subPattern == "" {
return ""
}

if node != nil {
e := node.endpoints[m]
return e.pattern
pattern = strings.TrimSuffix(pattern, "/*")
pattern += subPattern
}

return ""
return pattern
}

// NotFoundHandler returns the default Mux 404 responder whenever a route
Expand Down
50 changes: 46 additions & 4 deletions mux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1850,6 +1850,11 @@ func TestMuxFind(t *testing.T) {
w.Header().Set("X-Test", "yes")
w.Write([]byte("bye"))
})
r.Route("/yo", func(r Router) {
r.Get("/sup", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("sup"))
})
})
r.Route("/articles", func(r Router) {
r.Get("/{id}", func(w http.ResponseWriter, r *http.Request) {
id := URLParam(r, "id")
Expand All @@ -1868,17 +1873,54 @@ func TestMuxFind(t *testing.T) {
w.Write([]byte("user:" + id))
})
})
r.Route("/api", func(r Router) {
r.Route("/groups", func(r Router) {
r.Route("/v2", func(r Router) {
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("groups"))
})
r.Post("/{id}", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("POST groups"))
})
})
})
})

tctx := NewRouteContext()

tctx.Reset()
if r.Find(tctx, "GET", "/users/1") == "/users/{id}" {
t.Fatal("expecting to find match for route:", "GET", "/users/1")
if r.Find(tctx, "GET", "") == "/" {
t.Fatal("expecting to find pattern / for route: GET")
}

tctx.Reset()
if r.Find(tctx, "HEAD", "/articles/10") == "/articles/{id}" {
t.Fatal("not expecting to find match for route:", "HEAD", "/articles/10")
if r.Find(tctx, "GET", "/nope") != "" {
t.Fatal("not expecting to find pattern for route: GET /nope")
}

tctx.Reset()
if r.Find(tctx, "GET", "/users/1") != "/users/{id}" {
t.Fatal("expecting to find pattern /users/{id} for route: GET /users/1")
}

tctx.Reset()
if r.Find(tctx, "HEAD", "/articles/10") != "" {
t.Fatal("not expecting to find pattern for route: HEAD /articles/10")
}

tctx.Reset()
if r.Find(tctx, "GET", "/yo/sup") != "/yo/sup" {
t.Fatal("expecting to find pattern /yo/sup for route: GET /yo/sup")
}

tctx.Reset()
if r.Find(tctx, "GET", "/api/groups/v2/") != "/api/groups/v2/" {
t.Fatal("expecting to find pattern /api/groups/v2/ for route: GET /api/groups/v2/")
}

tctx.Reset()
if r.Find(tctx, "POST", "/api/groups/v2/1") != "/api/groups/v2/{id}" {
t.Fatal("expecting to find pattern /api/groups/v2/{id} for route: POST /api/groups/v2/1")
}
}

Expand Down

0 comments on commit 6ceb498

Please sign in to comment.