Skip to content

fix: deduplicate HTTP methods in 405 Allow header#1047

Open
veeceey wants to merge 2 commits into
go-chi:masterfrom
veeceey:fix/deduplicate-405-allow-header
Open

fix: deduplicate HTTP methods in 405 Allow header#1047
veeceey wants to merge 2 commits into
go-chi:masterfrom
veeceey:fix/deduplicate-405-allow-header

Conversation

@veeceey

@veeceey veeceey commented Feb 10, 2026

Copy link
Copy Markdown

Summary

Fixes #996

When overlapping wildcard routes match the same path (e.g., /article/1-2-3 matching /article/{a}, /article/{b}-{c}, /article/{b}-{c}-{d}), the tree traversal appends the same HTTP method to methodsAllowed multiple times. This causes the Allow header in 405 responses to contain duplicate entries:

Allow: POST POST POST POST

Root cause: In tree.go, findRoute iterates through matching nodes and appends each node's endpoint methods to rctx.methodsAllowed. When multiple wildcard patterns match the same path, the same method gets appended once per matching node.

Fix: In methodNotAllowedHandler, deduplicate the methodsAllowed slice using a seen-map before building the closure. Each method now appears exactly once in the header regardless of how many overlapping routes matched.

Before:

Status: 405 Method Not Allowed
Allow: POST POST POST POST

After:

Status: 405 Method Not Allowed
Allow: POST

Commits

  1. test: add test for duplicate methods in 405 Allow header — Adds TestMethodNotAllowedDuplicateAllow that reproduces the exact scenario from Duplicate HTTP methods in 405 Allow header #996 (registers overlapping wildcard routes with the same method and asserts the Allow header has no duplicates).
  2. fix: deduplicate HTTP methods in 405 Allow header — Deduplicates methodsAllowed using a simple seen-map before constructing the handler closure.

Test plan

  • New test TestMethodNotAllowedDuplicateAllow reproduces the exact scenario from Duplicate HTTP methods in 405 Allow header #996
  • Existing TestMethodNotAllowed continues to pass (verifies multiple distinct methods like GET and HEAD still appear correctly)
  • Existing TestMuxNestedMethodNotAllowed continues to pass
  • Full test suite passes: go test ./...

Comment thread mux.go Outdated
Comment on lines +529 to +532
for m, name := range reverseMethodMap {
if allowed&m != 0 {
w.Header().Add("Allow", name)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, thank you for this contribution.

Would you mind splitting the tests into a first commit?

I feel like the bitwise implementation is a bit too complex. Perhaps we can iterate on the second commit?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, thanks for the feedback! I've split it into two commits:

  1. test: add test for duplicate methods in 405 Allow header — just the test that reproduces Duplicate HTTP methods in 405 Allow header #996
  2. fix: deduplicate HTTP methods in 405 Allow header — the actual fix

I also replaced the bitwise approach with a simple seen-map to deduplicate the methodsAllowed slice before building the closure. It keeps the original iteration pattern over the slice (instead of iterating reverseMethodMap) so the behavior is more straightforward. Let me know what you think!

@veeceey veeceey force-pushed the fix/deduplicate-405-allow-header branch from 44ecca2 to 843c7c2 Compare February 11, 2026 07:03
@veeceey

veeceey commented Feb 19, 2026

Copy link
Copy Markdown
Author

Hi @VojtechVitek, just a friendly follow-up — I've split the commits as you suggested (test first, then fix) and replaced the bitwise approach with a simpler seen-map for deduplication. Would love your thoughts on the updated approach when you get a chance. Thanks!

Reproduces go-chi#996: when overlapping wildcard routes match the same path
(e.g., /article/1-2-3 matching /article/{a}, /article/{b}-{c},
/article/{b}-{c}-{d}), the Allow header in 405 responses contains
duplicate entries like "Allow: POST POST POST POST".

This test currently fails and will be fixed in the next commit.
Use slices.Sort + slices.Compact to deduplicate the methodsAllowed
slice before constructing the handler closure. This avoids duplicate
entries in the Allow header when overlapping wildcard routes match
the same path.

Fixes go-chi#996
@veeceey veeceey force-pushed the fix/deduplicate-405-allow-header branch from 843c7c2 to 9b59565 Compare February 24, 2026 07:31
@veeceey

veeceey commented Mar 15, 2026

Copy link
Copy Markdown
Author

ping - small fix for the duplicate methods in the 405 Allow header. would appreciate a look when you have time

@themavik themavik left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slices.Sort + Compact on the methodsAllowed slice removes duplicate methodTyp entries before methodNotAllowedHandler builds Allow. nit: sorting can change method order relative to registration—note that if anyone snapshots the header literally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Duplicate HTTP methods in 405 Allow header

3 participants