Skip to content

Commit 3efd66d

Browse files
vishrclaude
andcommitted
test: add companion test demonstrating group catch-all masking
Addresses final review: converts the "verified empirically" comment into an actual test. TestGroupRoute_catchAllMasksMethodHandling registers a group-wide catch-all and asserts it masks both the 405 method-mismatch and the automatic OPTIONS (204) response as 404 — the regression the 405/OPTIONS gate tests guard against. Makes the rationale self-proving in-repo. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 39dbf3f commit 3efd66d

1 file changed

Lines changed: 34 additions & 4 deletions

File tree

group_method_handling_test.go

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ import (
1818
// They double as a regression gate. Registering a group-level catch-all — whether
1919
// manually via g.RouteNotFound("/*", ...) or automatically (as proposed in #2996 to
2020
// fix CORS-on-group preflight) — makes that catch-all match every method, which masks
21-
// both 405 and v5's automatic OPTIONS response as 404. Verified empirically: with such
22-
// a catch-all in place, "POST /api/users" returns 404 instead of 405 and
23-
// "OPTIONS /api/users" returns 404 instead of 204. If that behavior reaches this
24-
// branch, the first two tests below fail.
21+
// both 405 and v5's automatic OPTIONS response as 404 — demonstrated directly by
22+
// TestGroupRoute_catchAllMasksMethodHandling below. If that masking becomes the
23+
// default (e.g. #2996 lands), the first two tests below fail.
2524

2625
// A method mismatch on an existing group route must return 405 with the allowed
2726
// methods, not be masked to 404.
@@ -83,3 +82,34 @@ func TestGroup_doesNotAffectRootRoutes(t *testing.T) {
8382
assert.Equal(t, http.StatusOK, status)
8483
assert.Equal(t, "root", body)
8584
}
85+
86+
// Characterization of the regression the 405/OPTIONS tests above guard against:
87+
// registering a group-wide catch-all (the manual equivalent of #2996's auto-
88+
// registration) makes it match every method, so method mismatches and the automatic
89+
// OPTIONS response are masked as 404 even though the concrete route still resolves.
90+
// If a future change teaches the catch-all to preserve method semantics, update this.
91+
func TestGroupRoute_catchAllMasksMethodHandling(t *testing.T) {
92+
e := New()
93+
g := e.Group("/api")
94+
g.GET("/users", func(c *Context) error { return c.String(http.StatusOK, "users") })
95+
g.RouteNotFound("/*", func(c *Context) error { return c.NoContent(http.StatusNotFound) })
96+
97+
// The concrete route still resolves.
98+
status, body := request(http.MethodGet, "/api/users", e)
99+
assert.Equal(t, http.StatusOK, status)
100+
assert.Equal(t, "users", body)
101+
102+
// But the catch-all masks the method mismatch (would be 405) ...
103+
post := httptest.NewRequest(http.MethodPost, "/api/users", nil)
104+
postRec := httptest.NewRecorder()
105+
e.ServeHTTP(postRec, post)
106+
assert.Equal(t, http.StatusNotFound, postRec.Code,
107+
"a group-wide catch-all masks the 405 method-mismatch as 404")
108+
109+
// ... and the automatic OPTIONS response (would be 204).
110+
opts := httptest.NewRequest(http.MethodOptions, "/api/users", nil)
111+
optsRec := httptest.NewRecorder()
112+
e.ServeHTTP(optsRec, opts)
113+
assert.Equal(t, http.StatusNotFound, optsRec.Code,
114+
"a group-wide catch-all masks the automatic OPTIONS (204) response as 404")
115+
}

0 commit comments

Comments
 (0)