shashank created CAMEL-25050:
--------------------------------
Summary: variableReceive into a route: or group: variable stores
the header variables under a route (group) with the id "header", so
route:header:resp.status does not find them
Key: CAMEL-25050
URL: https://issues.apache.org/jira/browse/CAMEL-25050
Project: Camel
Issue Type: Bug
Components: camel-core
Reporter: shashank
With {{variableReceive}} ({{toV}}, {{enrich}}, {{pollEnrich}}, {{toD}},
{{fromV}}) the received body is stored in the variable and each received header
as {{header:NAME.KEY}}
({{ExchangeHelper.setVariableFromMessageBodyAndHeaders}}). For a route or group
variable, NAME is the resolved repository name ({{rs:resp}} for {{route:resp}}
in route {{rs}}, {{myGroup:resp}} for {{group:myGroup:resp}}), so the header
key becomes {{header:rs:resp.status}}. {{RouteVariableRepository}} and
{{GroupVariableRepository}} take the text before the first colon as the route
(group) id. The header variables therefore end up in a route (group) whose id
is {{header}}, not in the route or group of the variable:
{noformat}
toV("direct:svc", null, "route:resp") in route rs, reply header status=200:
route repository names: [header:rs:resp.status, rs:resp]
toV("direct:svc", null, "group:myGroup:resp"):
group repository names: [header:myGroup:resp.status, myGroup:resp]
{noformat}
Consequences:
* The body is read with {{route:resp}}, but the header can only be read with
the internal key {{route:header:rs:resp.status}}. The names a user would try
return null:
{noformat}
route rs, after toV into route:resp (reply header status=200)
getVariable("route:resp") Bye Hello
getVariable("route:header:rs:resp.status") 200
getVariable("route:header:resp.status") null
getVariable("route:rs:header:resp.status") null
getVariable("header:route:resp.status") null
after toV into group:myGroup:resp
getVariable("group:header:myGroup:resp.status") 200
getVariable("group:myGroup:header:resp.status") null
getVariable("header:group:myGroup:resp.status") null
{noformat}
{{route:header:resp.status}} is resolved as variable {{resp.status}} of a route
named {{header}}: {{ExchangeHelper.resolveVariableRepositoryName}} only adds
the current route id when the name has no colon.
* The exchange repository returns all header variables of a variable as a map
for {{header:resp}} (a map with status=200) and removes them all for
{{removeVariable("header:resp")}}. The route and group repositories have no
such lookup: {{route:header:rs:resp}} returns null.
* Removing a route removes its variables ({{DefaultVariableRepositoryFactory}}
calls {{removeVariable(routeId + ":*")}}), but not the header variables of its
route variables, because they live under the id {{header}}. After
{{removeRoute("rs")}} the route repository still has {{header:rs:resp.status}}.
* {{GroupVariableRepository.getGroupIds()}} returns the keys of its group map,
so it includes a group {{header}} that no route uses.
* The header variables of all routes (all groups) share one map, so the removal
of the old header variables added by CAMEL-25035 scans that shared map instead
of the map of the variable's route or group.
Reproduced on 4.23.0-SNAPSHOT (branch of PR #26910; the naming is the same on
main, the PR does not change it) with a {{ContextTestSupport}} test that reads
the names above after {{toV}}.
*Proposed fix* (a behaviour change, so it needs a decision on the naming):
store the header variables of a route or group variable in the map of that
route or group, with the key {{header:resp.KEY}} under the id {{rs}}, that is
the repository name {{rs:header:resp.status}}. Then:
* resolve {{route:header:resp.status}} to the current route like
{{route:resp}}, and accept {{route:rs:header:resp.status}} with an explicit
route id; the same for groups with {{group:myGroup:header:resp.status}};
* removing a route removes the header variables of its variables too;
* the removal in {{setVariableFromMessageBodyAndHeaders}} only scans the map of
the variable's route or group;
* optionally support the {{header:resp}} map lookup and removal in the route
and group repositories, as the exchange repository does.
Compatibility: {{route:header:rs:resp.status}} (the only name that works today)
would no longer find the header, and {{route:header:x}} would no longer mean
variable {{x}} of a route with the id {{header}}. The alternative is to keep
the storage and document {{route:header:ROUTEID:NAME.KEY}} and
{{group:header:GROUPID:NAME.KEY}} as the names to use in {{variables.adoc}}.
Found while fixing CAMEL-25035 (PR #26910), where the tests read the route and
group header variables with {{route:header:rs:resp.status}} and
{{group:header:myGroup:resp.status}}.
_Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)