Horse Advanced Routing Skill
This skill guides AI agents in maintaining, expanding, and debugging Advanced Routing features (Regular Expression constraints and Optional path parameters) within the Horse framework.
💡 Syntax Reference
- Optional parameters:
:paramName?- Example:
/users/:id?
- Example:
- Regex constraints:
:paramName(regexPattern)- Example:
/users/:id(\d+)
- Example:
- Legacy segment Regex:
(regexPattern)(Keep for backwards compatibility only)- Example:
/users/(\d+)
- Example:
⚙️ Architecture and Execution Flow
1. Regex Helper (src/Horse.Core.Regex.pas)
Always use the unified THorseRegex abstraction. Do NOT import System.RegularExpressions (Delphi) or RegExpr (FPC) directly in routers to prevent cross-compilation breaks.
- Use
THorseRegex.Create(APattern)to instantiate. - Use
THorseRegex.Match(AContent)which returnsBooleanindicating if the exact string matches the pattern. - Always free the regex matcher instance inside the node destructions (
TRadixNode.Destroy/THorseRouterTree.Destroy).
2. Parameter Injection
When a path segment matches a route parameter, always ensure it is registered in THorseRequest.Params even if optional and empty:
- Optional parameter missing →
Params.Items['param'] = ''. - Ensure backtracking logic in
CallNextPath(Tree) andFindNode(Radix) clears parameters during path rejection to prevent parameters from bleeding into other matched paths.
3. Route Precedence
When routing, the engines prioritize matches as follows:
- Exact static segment matches (
/users/new) - Regular expression matched parameters (
/users/:id(\d+)) - Optional or general parameters (
/users/:id?)
🧪 Testing Guidelines
- Always write integration tests in
tests/src/tests/Tests.Integration.AdvancedRouting.pasverifying bothTHorseRadixRouterandTHorseRouterTree. - Test real network calls with
System.Net.HttpClientto confirm full transport compatibility. - Ensure ports are freed properly during TearDown using the
ClearGlobalStatehelper.