diff --git a/gin.go b/gin.go index 2e033bf3..434b1651 100644 --- a/gin.go +++ b/gin.go @@ -743,6 +743,7 @@ func (engine *Engine) handleHTTPRequest(c *Context) { if tree.method == httpMethod { continue } + *c.skippedNodes = (*c.skippedNodes)[:0] if value := tree.root.getValue(rPath, nil, c.skippedNodes, unescape); value.handlers != nil { allowed = append(allowed, tree.method) } diff --git a/routes_test.go b/routes_test.go index 1cae3fce..4e85db40 100644 --- a/routes_test.go +++ b/routes_test.go @@ -527,6 +527,23 @@ func TestRouteNotAllowedEnabled3(t *testing.T) { assert.Contains(t, allowed, http.MethodPost) } +func TestRouteNotAllowedDoesNotReuseSkippedNodes(t *testing.T) { + router := New() + router.HandleMethodNotAllowed = true + router.POST("/b", func(c *Context) {}) + router.POST("/:p0", func(c *Context) {}) + router.PUT("/a/:p1", func(c *Context) {}) + + // The POST probe for the Allow header matches static "/b" while + // recording the skipped wildcard ":p0". handleHTTPRequest must reset + // c.skippedNodes before probing the PUT tree, or the stale entry + // leaks the POST route into the PUT lookup and PUT is wrongly + // reported in the Allow header. + w := PerformRequest(router, http.MethodGet, "/b") + assert.Equal(t, http.StatusMethodNotAllowed, w.Code) + assert.Equal(t, http.MethodPost, w.Header().Get("Allow")) +} + func TestRouteNotAllowedDisabled(t *testing.T) { router := New() router.HandleMethodNotAllowed = false