Skip to content

Commit 2e1ed48

Browse files
authored
document group auto-404
1 parent a2dea4e commit 2e1ed48

1 file changed

Lines changed: 49 additions & 4 deletions

File tree

group_test.go

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -801,20 +801,27 @@ func TestGroup_RouteNotFoundWithMiddleware(t *testing.T) {
801801
expectMiddlewareCalled: true, // because RouteNotFound is added after middleware is added
802802
},
803803
{
804-
name: "ok, default group 404 handler is called with middleware",
804+
// #2485: a group that auto-registers 404 routes (because it has
805+
// middleware) falls back to the Router's configured NotFoundHandler,
806+
// NOT to a later e.RouteNotFound("/*", ...) call. The group's nil
807+
// handler is resolved to r.notFoundHandler at registration time, and
808+
// e.RouteNotFound only adds a tree route that the group's own catch-all
809+
// shadows. To customise the group 404, configure RouterConfig.NotFoundHandler
810+
// (see TestGroup_RouteNotFoundUsesRouterConfig).
811+
name: "ok, group auto-404 uses configured NotFoundHandler, not later e.RouteNotFound",
805812
givenCustom404: false,
806813
whenURL: "/group/test3",
807814
expectBody: "404 (global) GET /group/*",
808815
expectCode: http.StatusNotFound,
809-
expectMiddlewareCalled: true, // because RouteNotFound is added before middleware is added
816+
expectMiddlewareCalled: true, // group middleware still wraps the auto 404 route
810817
},
811818
{
812-
name: "ok, (no slash) default group 404 handler is called with middleware",
819+
name: "ok, (no slash) group auto-404 uses configured NotFoundHandler, not later e.RouteNotFound",
813820
givenCustom404: false,
814821
whenURL: "/group",
815822
expectBody: "404 (global) GET /group",
816823
expectCode: http.StatusNotFound,
817-
expectMiddlewareCalled: true, // because RouteNotFound is added before middleware is added
824+
expectMiddlewareCalled: true, // group middleware still wraps the auto 404 route
818825
},
819826
}
820827
for _, tc := range testCases {
@@ -937,3 +944,41 @@ func TestGroup_UseMultipleTimes(t *testing.T) {
937944
})
938945

939946
}
947+
948+
// TestGroup_RouteNotFoundUsesRouterConfig documents the supported way to
949+
// customise the 404 handler for groups that auto-register catch-all routes
950+
// (i.e. groups that have middleware). Per maintainer guidance on #2485/#3052,
951+
// adding a route via e.RouteNotFound must NOT have side effects on the Router;
952+
// instead configure RouterConfig.NotFoundHandler, which the group's auto 404
953+
// routes resolve to at registration time and which group middleware wraps.
954+
func TestGroup_RouteNotFoundUsesRouterConfig(t *testing.T) {
955+
customNotFound := func(c *Context) error {
956+
return c.String(http.StatusNotFound, "custom-404 "+c.Request().Method+" "+c.Path())
957+
}
958+
959+
e := NewWithConfig(Config{
960+
Router: NewRouter(RouterConfig{
961+
NotFoundHandler: customNotFound,
962+
}),
963+
})
964+
965+
middlewareCalled := false
966+
g := e.Group("/v0")
967+
g.Use(func(next HandlerFunc) HandlerFunc {
968+
return func(c *Context) error {
969+
middlewareCalled = true
970+
return next(c)
971+
}
972+
})
973+
g.POST("/resource", func(c *Context) error { return c.NoContent(http.StatusOK) })
974+
975+
// Unmatched path inside the group: the group's auto-registered catch-all
976+
// resolves to the configured NotFoundHandler, and group middleware wraps it.
977+
req := httptest.NewRequest(http.MethodPost, "/v0/missing", nil)
978+
rec := httptest.NewRecorder()
979+
e.ServeHTTP(rec, req)
980+
981+
assert.Equal(t, http.StatusNotFound, rec.Code)
982+
assert.Equal(t, "custom-404 POST /v0/*", rec.Body.String())
983+
assert.True(t, middlewareCalled, "group middleware must wrap the auto 404 route")
984+
}

0 commit comments

Comments
 (0)