Skip to content

fix(router): stop double-encoding route variables when URL rewriting is off - #3667

Merged
bpamiri merged 1 commit into
developfrom
claude/wheels-framework-bug-review-odsc9d-rewrite-off-encoding
Sep 27, 2026
Merged

bpamiri merged 1 commit into
developfrom
claude/wheels-framework-bug-review-odsc9d-rewrite-off-encoding

Conversation

@bpamiri

@bpamiri bpamiri commented Sep 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

With URLRewriting="Off", $urlForSubstituteVariables() replaces the route pattern with ?controller=…&action=…&key=…&format=…. So a custom route variable such as [slug] is "not in pattern" and gets appended to params instead. The value appended was the one that had already been URL-encoded, and $constructParams encodes params again:

  • urlFor(route="post", slug="a b") → slug=a%2Bb, so the server receives "a+b".
  • On the HTML-attribute path (linkTo, startFormTag), the & inside the encoded entity split the value into junk parameters: slug=a&%23x2b%3Bb=.

Fix: the raw value is kept and appended in the not-in-pattern branch, so $constructParams encodes it exactly once. When encoding is on, only & and = are escaped (%26, %3D). Those are the delimiters $constructParams splits on, and escaping them is what the params docs ask for. This keeps slug="a&b" intact. With encode=false the output is unchanged. On/Partial modes substitute into the path and were never affected.

Related Issue

None filed. Found during a framework bug review.

Type of Change

  • Bug fix

Feature Completeness Checklist

  • DCO sign-off
  • Tests: 3 cases in global/urlforSpec.cfc:
    • Off mode, exact output for a space, & and =;
    • Off mode with $encodeForHtmlAttribute=true, compared against EncodeForHTMLAttribute("a+b") so it holds on every engine;
    • Partial mode unchanged.
  • Changelog fragment: changelog.d/rewrite-off-route-variable-encoding.fixed.md
  • Test runner passes: CI is the first full-suite run.

Test Plan

I ran the real $urlForSubstituteVariables (old and new) and $constructParams, extracted verbatim, on Lucee 6.2. The ESAPI encoders were stubbed with Java equivalents.

case old new
Off, "a b" slug=a%2Bb slug=a+b
Off, HTML-attribute encoding, "a b" slug=a&%23x2b%3Bb= slug=a+b
Off, /, &, = without HTML encoding correct same
Partial / On — identical

🤖 Generated with Claude Code

https://claude.ai/code/session_018RdXpVKos1AZ24dM4X8wL1


Generated by Claude Code

…is off

With URLRewriting="Off", urlFor() replaces the route pattern with the
`?controller=...&action=...&key=...&format=...` query string, so a custom route
variable such as `[slug]` is not in the pattern and is appended to `params`.
$urlForSubstituteVariables appended the already URL-encoded (and, for linkTo /
startFormTag, HTML-attribute-encoded) value, and $constructParams encoded it again:
`slug="a b"` became `slug=a%2Bb` (server receives "a+b"), and with HTML encoding
the `&` of the `+` entity split the value into garbage params.

Append the raw value instead, escaping only the `&` / `=` delimiters that
$constructParams splits on, so the value is encoded exactly once. In-pattern
substitution (On / Partial) is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RdXpVKos1AZ24dM4X8wL1
Signed-off-by: Claude <noreply@anthropic.com>
@bpamiri
bpamiri merged commit f2238f6 into develop Sep 27, 2026
18 of 19 checks passed
@bpamiri
bpamiri deleted the claude/wheels-framework-bug-review-odsc9d-rewrite-off-encoding branch September 27, 2026 02:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants