Skip to content

Commit ec642f7

Browse files
committed
Fix group.RouteNotFound not working when group has attached middlewares
1 parent 5b36ce3 commit ec642f7

File tree

2 files changed

+76
-4
lines changed

2 files changed

+76
-4
lines changed

group.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ func (g *Group) Use(middleware ...MiddlewareFunc) {
2323
if len(g.middleware) == 0 {
2424
return
2525
}
26-
// Allow all requests to reach the group as they might get dropped if router
27-
// doesn't find a match, making none of the group middleware process.
28-
g.Any("", NotFoundHandler)
29-
g.Any("/*", NotFoundHandler)
26+
// group level middlewares are different from Echo `Pre` and `Use` middlewares (those are global). Group level middlewares
27+
// are only executed if they are added to the Router with route.
28+
// So we register catch all route (404 is a safe way to emulate route match) for this group and now during routing the
29+
// Router would find route to match our request path and therefore guarantee the middleware(s) will get executed.
30+
g.RouteNotFound("", NotFoundHandler)
31+
g.RouteNotFound("/*", NotFoundHandler)
3032
}
3133

3234
// CONNECT implements `Echo#CONNECT()` for sub-routes within the Group.

group_test.go

+70
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,73 @@ func TestGroup_RouteNotFound(t *testing.T) {
184184
})
185185
}
186186
}
187+
188+
func TestGroup_RouteNotFoundWithMiddleware(t *testing.T) {
189+
var testCases = []struct {
190+
name string
191+
givenCustom404 bool
192+
whenURL string
193+
expectBody interface{}
194+
expectCode int
195+
}{
196+
{
197+
name: "ok, custom 404 handler is called with middleware",
198+
givenCustom404: true,
199+
whenURL: "/group/test3",
200+
expectBody: "GET /group/*",
201+
expectCode: http.StatusNotFound,
202+
},
203+
{
204+
name: "ok, default group 404 handler is called with middleware",
205+
givenCustom404: false,
206+
whenURL: "/group/test3",
207+
expectBody: "{\"message\":\"Not Found\"}\n",
208+
expectCode: http.StatusNotFound,
209+
},
210+
{
211+
name: "ok, (no slash) default group 404 handler is called with middleware",
212+
givenCustom404: false,
213+
whenURL: "/group",
214+
expectBody: "{\"message\":\"Not Found\"}\n",
215+
expectCode: http.StatusNotFound,
216+
},
217+
}
218+
for _, tc := range testCases {
219+
t.Run(tc.name, func(t *testing.T) {
220+
221+
okHandler := func(c Context) error {
222+
return c.String(http.StatusOK, c.Request().Method+" "+c.Path())
223+
}
224+
notFoundHandler := func(c Context) error {
225+
return c.String(http.StatusNotFound, c.Request().Method+" "+c.Path())
226+
}
227+
228+
e := New()
229+
e.GET("/test1", okHandler)
230+
e.RouteNotFound("/*", notFoundHandler)
231+
232+
g := e.Group("/group")
233+
g.GET("/test1", okHandler)
234+
235+
middlewareCalled := false
236+
g.Use(func(next HandlerFunc) HandlerFunc {
237+
return func(c Context) error {
238+
middlewareCalled = true
239+
return next(c)
240+
}
241+
})
242+
if tc.givenCustom404 {
243+
g.RouteNotFound("/*", notFoundHandler)
244+
}
245+
246+
req := httptest.NewRequest(http.MethodGet, tc.whenURL, nil)
247+
rec := httptest.NewRecorder()
248+
249+
e.ServeHTTP(rec, req)
250+
251+
assert.True(t, middlewareCalled)
252+
assert.Equal(t, tc.expectCode, rec.Code)
253+
assert.Equal(t, tc.expectBody, rec.Body.String())
254+
})
255+
}
256+
}

0 commit comments

Comments
 (0)