From 700d4416aa8600516b37e25f7c3ad1a2990fbbcf Mon Sep 17 00:00:00 2001 From: Gavin Zhang Date: Sat, 4 Apr 2026 17:02:46 +0800 Subject: [PATCH] docs(engine): clarify Use() registration order --- docs/doc.md | 4 ++++ gin.go | 5 +++-- gin_test.go | 31 +++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/docs/doc.md b/docs/doc.md index d1c33b87..d40cea90 100644 --- a/docs/doc.md +++ b/docs/doc.md @@ -459,6 +459,10 @@ func main() { } ``` +Attach global middleware before registering routes. Routes added before a `Use()` call are not +retroactively wrapped, while `404` and `405` handlers are rebuilt from the current global +middleware chain. + ### Custom Middleware ```go diff --git a/gin.go b/gin.go index 2e033bf3..2b99119b 100644 --- a/gin.go +++ b/gin.go @@ -334,8 +334,9 @@ func (engine *Engine) NoMethod(handlers ...HandlerFunc) { engine.rebuild405Handlers() } -// Use attaches a global middleware to the router. i.e. the middleware attached through Use() will be -// included in the handlers chain for every single request. Even 404, 405, static files... +// Use attaches a global middleware to the router. Middleware attached through Use() is included +// in the handlers chain for routes registered after the call. For 404 and 405 requests, Gin +// rebuilds the handler chain from the current middleware set. // For example, this is the right place for a logger or error management middleware. func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes { engine.RouterGroup.Use(middleware...) diff --git a/gin_test.go b/gin_test.go index a9cf1755..e96cfb6d 100644 --- a/gin_test.go +++ b/gin_test.go @@ -570,6 +570,37 @@ func TestRebuild404Handlers(t *testing.T) { compareFunc(t, router.allNoRoute[1], middleware0) } +func TestUseOnlyAppliesToRoutesRegisteredAfterIt(t *testing.T) { + signature := "" + router := New() + + router.GET("/before", func(c *Context) { + signature += "A" + c.Status(http.StatusNoContent) + }) + + router.Use(func(c *Context) { + signature += "M" + c.Next() + signature += "N" + }) + + router.GET("/after", func(c *Context) { + signature += "B" + c.Status(http.StatusNoContent) + }) + + w := PerformRequest(router, http.MethodGet, "/before") + assert.Equal(t, http.StatusNoContent, w.Code) + assert.Equal(t, "A", signature) + + signature = "" + + w = PerformRequest(router, http.MethodGet, "/after") + assert.Equal(t, http.StatusNoContent, w.Code) + assert.Equal(t, "MBN", signature) +} + func TestNoMethodWithGlobalHandlers(t *testing.T) { var middleware0 HandlerFunc = func(c *Context) {} var middleware1 HandlerFunc = func(c *Context) {}