Tell the runtime whether routers deliver escaped path parameter values#2457
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Closes: #2455 Generated server wrappers bound path parameters without knowing whether the router had already percent-decoded them, so the runtime's unconditional unescape double-decoded values containing literal percent signs ("discount%20" arrived as "discount ", "15%off" failed binding). The wrappers now set the ValueIsUnescaped option added in runtime v1.5.0, which is the new minimum runtime version for generated code. The per-framework behavior was determined empirically through the parameter round-trip harness, and falls into three classes: - echo, echo v5 and chi route on URL.RawPath when it is non-empty, so they deliver decoded values normally but raw values exactly when the parameter contains an encoded slash (net/url only preserves RawPath for %2F-class escapes). Their wrappers pass the flag dynamically: ValueIsUnescaped: <request>.URL.RawPath == "". - gin, gorilla, iris and stdhttp always deliver decoded values (the first three route on the decoded path and reject encoded slashes with a 404); their wrappers pass ValueIsUnescaped: true. - fiber v2 and v3 deliver raw values; their wrappers leave the flag unset so the runtime keeps unescaping. Test enhancements for the above: - The round-trip harness gains a styled string path parameter (/simpleString/{param}) exercised with escape-hostile values — literal percents, spaces, reserved characters, unicode, an encoded slash, and a combined percent-plus-encoded-slash value — covering both branches of the dynamic flag. Frameworks that structurally cannot route encoded slashes assert the 404 so semantic changes in a framework surface here. - Fiber v3 gets a full round-trip harness leaf (generated server, implementation, and test), bringing it to parity with the other frameworks rather than being covered only by webhook tests. - stdhttp gets a single-route escaping probe, since its full round-trip run is still skipped on the digit-leading parameter panic (#2306). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
e88cf98 to
4a9f936
Compare
Greptile SummaryThis PR fixes a double-decoding bug (issue #2455) where path parameters containing literal percent signs were silently corrupted — e.g.
Confidence Score: 5/5Safe to merge — the change is a targeted bug fix with correct per-framework handling, regenerated fixtures that match the new templates, and comprehensive round-trip test coverage for every backend. All seven backend templates are updated with the correct ValueIsUnescaped value (three with a dynamic RawPath check, three with true, two intentionally left unset). The strict-server fixtures previously flagged in review with hardcoded true for chi/echo/echo5 are now correctly regenerated. The runtime version bump is justified and explicitly documented. The new testStringEscaping harness covers the full space of tricky values empirically, and fiber v3 now has a complete round-trip leaf on par with other frameworks. No files require special attention — all templates, their generated counterparts, and the test harness are consistent.
|
| Filename | Overview |
|---|---|
| pkg/codegen/templates/chi/chi-middleware.tmpl | Adds ValueIsUnescaped: r.URL.RawPath == "" for styled path params — correct dynamic flag, since chi routes on RawPath when non-empty (only for %2F-class escapes) and on Path otherwise. |
| pkg/codegen/templates/echo/echo-wrappers.tmpl | Adds ValueIsUnescaped: ctx.Request().URL.RawPath == "" — same correct dynamic flag as chi for echo's identical routing behaviour. |
| pkg/codegen/templates/gin/gin-wrappers.tmpl | Sets ValueIsUnescaped: true unconditionally — correct, since gin always delivers decoded values and rejects %2F-in-param with 404. |
| pkg/codegen/templates/stdhttp/std-http-middleware.tmpl | Sets ValueIsUnescaped: true — correct, net/http ServeMux's r.PathValue() returns decoded values; Go 1.22+ ServeMux routes on EscapedPath so %2F in a wildcard is correctly forwarded as a decoded slash. |
| pkg/codegen/templates/fiber/fiber-middleware.tmpl | No ValueIsUnescaped added — intentional, fiber v2 delivers raw (un-decoded) values so the runtime's default unescape behaviour is correct. |
| internal/test/parameters/roundtrip/param_roundtrip_test.go | Adds routesEncodedSlash flag to testImpl, integrates testStringEscaping sub-suite covering literal percents, spaces, unicode, encoded slashes, and the cross-term; correct per-framework flag values passed. |
| internal/test/parameters/roundtrip/stdhttp_escaping_test.go | New file: registers only the /simpleString/{param} route to work around the digit-leading panic, correctly accesses the exported ServerInterfaceWrapper with its ErrorHandlerFunc field. |
| internal/test/servers/strict/chi/server.gen.go | Correctly regenerated with ValueIsUnescaped: r.URL.RawPath == "" — the mismatch flagged in the previous review thread is now fixed. |
| internal/test/servers/strict/echo/server.gen.go | Correctly regenerated with ValueIsUnescaped: ctx.Request().URL.RawPath == "" — prior hardcoded true is fixed. |
| internal/test/go.mod | runtime dependency bumped from v1.4.2 to v1.5.0 to satisfy the new ValueIsUnescaped struct field; justified by the feature dependency. |
Reviews (2): Last reviewed commit: "Tell the runtime whether routers deliver..." | Re-trigger Greptile
Closes: #2455
Generated server wrappers bound path parameters without knowing whether the router had already percent-decoded them, so the runtime's unconditional unescape double-decoded values containing literal percent signs ("discount%20" arrived as "discount ", "15%off" failed binding). The wrappers now set the ValueIsUnescaped option added in runtime v1.5.0, which is the new minimum runtime version for generated code.
The per-framework behavior was determined empirically through the parameter round-trip harness, and falls into three classes:
Test enhancements for the above: