Skip to content

fix(routes): canonicalize path parameters so client calls match handlers (#505)#506

Open
imateusdev wants to merge 1 commit into
DeusData:mainfrom
imateusdev:fix/route-param-canonicalization
Open

fix(routes): canonicalize path parameters so client calls match handlers (#505)#506
imateusdev wants to merge 1 commit into
DeusData:mainfrom
imateusdev:fix/route-param-canonicalization

Conversation

@imateusdev

Copy link
Copy Markdown

What does this PR do?

Canonicalizes route-path parameter placeholders when building Route QNs so that
a client HTTP_CALLS and the server handler that serves it rendezvous on the same
Route node even when each side uses a different framework's placeholder syntax
(or a different parameter name).

Fixes #505.

Problem

Route QNs (__route__METHOD__/path) are the rendezvous key, but they were built
from the raw path. A Rust/Axum handler GET /players/{id} and a TypeScript client
call /players/:id therefore produced different QNs and never joined. Static
routes joined fine; parameterized routes (the bulk of a REST surface) did not:

Route<-[:HTTP_CALLS]- ∩ Route<-[:HANDLES]-  ==  ∅   (for parameterized paths)

Fix

New shared helper cbm_route_canon_path() (declared in pipeline_internal.h,
defined in pass_route_nodes.c) collapses each parameter token to a single {}:

Input Canonical
/players/:id /players/{}
/players/{id} /players/{}
/users/<int:id> /users/{}
/players/${id} /players/{}
/orders/{id}/items/{itemIndex} /orders/{}/items/{}

Applied to the path at every HTTP-route QN construction site
(pass_route_nodes.c, pass_parallel.c, pass_calls.c, pass_cross_repo.c);
broker/async/infra QNs are left untouched. The Route node's display name keeps
the original path — only the QN (identity/dedup key) is canonicalized — so the
existing ANY-vs-method reconciliation does the rest, exactly as it already does
for static routes.

Design note / tradeoff

Parameter names are intentionally discarded: /users/{id} and /users/{slug}
canonicalize to the same node. For REST surfaces these are virtually always the
same logical endpoint; flagging it here for reviewer visibility.

Tests

tests/test_route_canon.c — 11 unit cases covering each placeholder syntax, the
:id{id} convergence invariant, parameter-name agnosticism, literal : mid
segment, multiple params, NULL/empty, and tight-buffer truncation safety.

Verification

  • make -f Makefile.cbm cbm — clean build (-Wall -Wextra -Werror).
  • make -f Makefile.cbm test — full ASan/UBSan suite; the new route_canon
    suite passes 11/11 and no previously-passing test regresses.
  • clang-format-18 --dry-run --Werror clean on all changed files.

Checklist

  • Every commit is signed off (git commit -s)
  • Tests pass locally
  • Lint passes (clang-format) on changed files
  • New behavior is covered by a test (reproduce-first)

Route QNs (__route__METHOD__/path) are the rendezvous key for joining a client
HTTP_CALLS to the server handler that serves it, but they were built from the raw
path. Frameworks write path parameters with different placeholder syntaxes
(":id" Express/clients, "{id}" Axum/Spring/OpenAPI, "<id>" Flask/Rocket), so a
client call and its handler produced different QNs and never joined. Static
routes joined; parameterized routes (most of a REST surface) did not.

Add cbm_route_canon_path() which collapses each parameter token (":name",
"{name}", "<name>", "${...}") to a single "{}" token, and apply it to the path
at every HTTP-route QN construction site (pass_route_nodes, pass_parallel,
pass_calls, pass_cross_repo). Broker/async/infra QNs are left untouched. Only the
QN (identity/dedup key) is canonicalized; the Route node display name keeps the
original path. Parameter names are intentionally discarded so the same logical
endpoint matches across services that name the variable differently.

Adds tests/test_route_canon.c (11 cases). Fixes DeusData#505.

Signed-off-by: imateusdev <imateusdev@gmail.com>
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.

HTTP route matching never joins client calls to handlers for parameterized paths (:id vs {id} placeholder mismatch)

1 participant