Skip to content

Anchor trailing-slash stdhttp routes with {$} to match OpenAPI semantics#2460

Merged
mromaszewicz merged 1 commit into
mainfrom
fix/issue-2065
Jul 13, 2026
Merged

Anchor trailing-slash stdhttp routes with {$} to match OpenAPI semantics#2460
mromaszewicz merged 1 commit into
mainfrom
fix/issue-2065

Conversation

@mromaszewicz

Copy link
Copy Markdown
Member

Closes: #2065

A ServeMux pattern ending in '/' matches the whole subtree below it, while an OpenAPI path ending in '/' means exactly that path. Registering spec paths as subtree patterns both mismatched the spec's semantics and panicked at registration when two such patterns overlapped ambiguously (e.g. "/api/test/{id}/test2/" and "/api/test/test3/", which both match "/api/test/test3/test2/" with neither more specific).

SwaggerUriToStdHttpUri now appends the {$} end-of-URL anchor to any path ending in '/', generalizing the existing special case for the root path. The anchor is added after parameter-name sanitization so the '$' is not mistaken for a parameter.

Behavior change for existing specs with trailing-slash paths: such routes no longer act as catch-all subtrees, and requests to deeper paths now return 404, matching what the spec declares. ServeMux still redirects a request missing the trailing slash to the canonical path (with a 307), which the new test leaf pins alongside the issue's panic repro.

Since we are changing behavior in the direction of correctness, I am not flagifying this.

@mromaszewicz
mromaszewicz requested a review from a team as a code owner July 13, 2026 01:03
@mromaszewicz mromaszewicz added bug Something isn't working ☢️ breaking change This change would break existing users' code labels Jul 13, 2026
Closes: #2065

A ServeMux pattern ending in '/' matches the whole subtree below it,
while an OpenAPI path ending in '/' means exactly that path. Registering
spec paths as subtree patterns both mismatched the spec's semantics and
panicked at registration when two such patterns overlapped ambiguously
(e.g. "/api/test/{id}/test2/" and "/api/test/test3/", which both match
"/api/test/test3/test2/" with neither more specific).

SwaggerUriToStdHttpUri now appends the {$} end-of-URL anchor to any path
ending in '/', generalizing the existing special case for the root path.
The anchor is added after parameter-name sanitization so the '$' is not
mistaken for a parameter.

Behavior change for existing specs with trailing-slash paths: such routes
no longer act as catch-all subtrees, and requests to deeper paths now return
404, matching what the spec declares. ServeMux still redirects a request
missing the trailing slash to the canonical path (with a 307), which the
new test leaf pins alongside the issue's panic repro.

Since we are changing behavior in the direction of correctness, I am not
flagifying this.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes issue #2065 by generalizing the existing root-path {$} special case in SwaggerUriToStdHttpUri so that all OpenAPI paths ending in / are registered as {$}-anchored exact-match patterns in the net/http ServeMux, rather than open-ended subtree patterns. The fix is applied after parameter-name sanitization so the $ character is never interpreted as part of a wildcard name.

  • pkg/codegen/utils.go: Replaces the if uri == \"/\" special case with a general strings.HasSuffix(uri, \"/\") check that appends {$} to any trailing-slash path, correcting the OpenAPI exact-path semantic mismatch and eliminating the ServeMux registration panic when two such paths overlap ambiguously.
  • internal/test/servers/routers/trailing_slash/: New test fixture under the correct servers/routers/ category, with the issue OAS pattern generation without wildcard {$} causes panic in http.ServeMux due to pattern conflicts #2065 panic-repro spec, a unit test covering exact-match routing, sub-path 404 behavior, and trailing-slash redirects, plus a regenerated *.gen.go showing the {$}-anchored HandleFunc registrations.

Confidence Score: 5/5

Safe to merge; the change is a targeted, well-tested correction to stdhttp route registration semantics with no unrelated diff churn.

The core fix in utils.go is minimal and correct. The generated fixture confirms the right patterns are emitted. Tests cover the panic repro, exact routing, sub-path 404, and redirect behavior. No unrelated template changes; no other backends touched.

No files require special attention beyond server_test.go, which is missing the //go:build go1.22 build constraint already noted in a prior review thread.

Important Files Changed

Filename Overview
pkg/codegen/utils.go Generalizes the root-path {$} special case into a universal trailing-slash anchor for all paths, correctly placed after parameter sanitization so $ is never mistaken for a wildcard name.
pkg/codegen/utils_test.go Adds three unit-test cases covering the new {$}-anchoring logic for plain, parameterized, and literal trailing-slash paths.
internal/test/servers/routers/trailing_slash/server_test.go Integration test covering the panic-repro case from issue #2065, exact-match routing, 404 for sub-paths, and trailing-slash redirect; missing //go:build go1.22 build constraint (already flagged in prior review thread).
internal/test/servers/routers/trailing_slash/trailing_slash.gen.go Generated file correctly registers routes with {$} anchors; //go:build go1.22 tag present; size proportional to the change.
internal/test/servers/routers/trailing_slash/spec.yaml New spec with the exact two overlapping paths from issue #2065, placed correctly under servers/routers/ with provenance comment.

Reviews (2): Last reviewed commit: "Anchor trailing-slash stdhttp routes wit..." | Re-trigger Greptile

Comment thread internal/test/servers/routers/trailing_slash/server_test.go
Comment thread pkg/codegen/utils.go
@mromaszewicz
mromaszewicz merged commit 87e9aa2 into main Jul 13, 2026
28 checks passed
@mromaszewicz
mromaszewicz deleted the fix/issue-2065 branch July 13, 2026 01:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

☢️ breaking change This change would break existing users' code bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OAS pattern generation without wildcard {$} causes panic in http.ServeMux due to pattern conflicts

1 participant