Skip to content

feat: add Template.MODE_STARTS_WITH_SEGMENT matching mode - #1565

Merged
jlouvel merged 2 commits into
3.0from
feat/template-segment-matching
Nov 1, 2026
Merged

jlouvel merged 2 commits into
3.0from
feat/template-segment-matching

Conversation

@jlouvel

@jlouvel jlouvel commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator

Closes #1564.

Adds Template.MODE_STARTS_WITH_SEGMENT: like MODE_STARTS_WITH, but the match must end on a URI path segment boundary, meaning the end of the string, a following /, ?, ; or #, or a match that itself ends with /. A route attached to /mcp then matches /mcp, /mcp/tools and /mcp?x=1, but not /mcpx or /mcp-admin/tools.

Changes

  • Template: new constant, and a private matches() used by both match() and parse(), so scoring and parsing agree. MODE_EQUALS and MODE_STARTS_WITH behave as before.
  • TemplateTestCase: boundaries (/, ?, ;, #, end of string), a template ending with /, an empty template, variable parsing, and a check that MODE_STARTS_WITH still matches by character.
  • RouterTestCase: catch-all routers mounted at /mcp, /mcp-admin and the root, with /mcpx falling through to the root.
  • changes.md: entry under 3.0 Milestone 2, Enhancements.

Validation

./mvnw -B -pl org.restlet verify: 2,222 tests passed, 0 failures. Spotless, JaCoCo and SpotBugs checks are met (8 findings, under the existing threshold of 9).

Not included

Making this the default mode for Router and Directory targets would change behaviour for existing applications. The issue raises that as an open question.

@jlouvel jlouvel self-assigned this Oct 25, 2026
@jlouvel
jlouvel requested a review from thboileau October 25, 2026 18:18

@jlouvel jlouvel left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@thboileau Could you review this enhancement?

Copilot AI left a comment

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.

🟡 Changes recommended

The post-match boundary check prevents regex backtracking to an earlier valid boundary, causing both match() and parse() to reject valid URI prefixes.

1 open issue
What changed in this PR

Adds an opt-in segment-aware prefix matching mode to Restlet’s URI templates, addressing #1564 without changing existing routing defaults.

Changes:

  • Introduces MODE_STARTS_WITH_SEGMENT with shared matching logic for match() and parse().
  • Adds template boundary, variable parsing, and nested-router tests.
  • Documents the new mode in the changelog.
File Description
org.restlet/​src/​test/​java/​org/​restlet/​routing/​TemplateTestCase.java Tests boundaries, parsing, and existing prefix behavior.
org.restlet/​src/​test/​java/​org/​restlet/​routing/​RouterTestCase.java Tests segment-aware mounts and root fallback.
org.restlet/​src/​main/​java/​org/​restlet/​routing/​Template.java Adds the mode and shared boundary-checking logic.
changes.md Records the new matching mode and its routing use case.

Review effort: Balanced

jlouvel and others added 2 commits October 31, 2026 17:59
Like MODE_STARTS_WITH, but the match must end on a URI path segment
boundary (end of string, '/', '?', ';' or '#', or a match ending with
'/'). A route attached to /mcp then matches /mcp, /mcp/tools and
/mcp?x=1 but not /mcpx, which makes it safe to mount several routers
or applications under path prefixes on one connector.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Check the segment boundary inside the regex instead of after
lookingAt(), so a greedy variable can backtrack to an earlier valid
boundary, as in "/files/{name}.json" matching "/files/a.json;b.jsonx".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Jerome Louvel <374450+jlouvel@users.noreply.github.com>
@jlouvel
jlouvel force-pushed the feat/template-segment-matching branch from 2587eaf to d484423 Compare October 31, 2026 22:02
@sonarqubecloud

Copy link
Copy Markdown

@jlouvel
jlouvel merged commit 14aa424 into 3.0 Nov 1, 2026
3 of 4 checks passed
@jlouvel
jlouvel deleted the feat/template-segment-matching branch November 1, 2026 02:06
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.

2 participants