fix(routes): canonicalize path parameters so client calls match handlers (#505)#506
Conversation
|
Thanks @imateusdev — the route-param canonicalization is correct and well-tested. The CI red here is a cppcheck false-positive: at Please add a targeted |
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>
d472dbc to
8b81367
Compare
|
Thanks @DeusData! Done — and a heads-up on a second issue I hit along the way. 1. cppcheck false-positive ( if (out == NULL || out_sz == 0) {
/* WHY: cppcheck value-flow follows a caller that passes an as-yet
* uninitialized output buffer (e.g. `char cpath[256];`) and flags this
* `return out` as uninitvar. False positive: we only return the pointer
* here and never read the buffer; returning it (NULL, or a buffer too
* small to write into) is the intended early-out contract. */
// cppcheck-suppress uninitvar
return out;
}2. Merge conflict with #485 — while pushing I noticed the branch had gone if (strcmp(edge->type, "HTTP_CALLS") == 0 &&
!cbm_service_pattern_is_http_route_literal(url, callee)) {
return; // #485: reject filesystem paths
}
...
cbm_route_canon_path(url, cpath, sizeof(cpath)) // this PR: canonicalize survivorsForce-pushed the rebased commit ( |
What does this PR do?
Canonicalizes route-path parameter placeholders when building Route QNs so that
a client
HTTP_CALLSand the server handler that serves it rendezvous on the sameRoutenode 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 builtfrom the raw path. A Rust/Axum handler
GET /players/{id}and a TypeScript clientcall
/players/:idtherefore produced different QNs and never joined. Staticroutes joined fine; parameterized routes (the bulk of a REST surface) did not:
Fix
New shared helper
cbm_route_canon_path()(declared inpipeline_internal.h,defined in
pass_route_nodes.c) collapses each parameter token to a single{}:/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
namekeepsthe 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:midsegment, 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 newroute_canonsuite passes 11/11 and no previously-passing test regresses.
clang-format-18 --dry-run --Werrorclean on all changed files.Checklist
git commit -s)