[
https://issues.apache.org/jira/browse/CAMEL-24147?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Claus Ibsen resolved CAMEL-24147.
---------------------------------
Resolution: Fixed
> camel-lra: participant callback URLs are not URL-encoded and parseQuery is
> lossy - compensation breaks for URIs with query parameters or options with
> special characters
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-24147
> URL: https://issues.apache.org/jira/browse/CAMEL-24147
> Project: Camel
> Issue Type: Bug
> Components: camel-lra
> Reporter: Federico Mariani
> Assignee: Claus Ibsen
> Priority: Major
> Fix For: 4.22.0
>
> Attachments: LRAUrlEncodingIssueTest.java
>
>
> h3. Problem
> Two related defects:
> # {{LRAUrlBuilder.query()}} concatenates keys and values raw
> (components/camel-lra/src/main/java/org/apache/camel/service/lra/LRAUrlBuilder.java:89-98)
> - no {{URLEncoder}}. {{LRAClient.join()}} embeds the compensation/completion
> endpoint URI and all evaluated saga option values as query parameters of the
> participant callback URL registered with the LRA coordinator (Link header).
> Any value containing {{&}}, {{=}}, {{#}}, {{+}} or a space corrupts the
> callback URL.
> # {{LRASagaRoutes.parseQuery}} splits with {{element.split("=")}} and takes
> index 1 (LRASagaRoutes.java:71-73), so even a single embedded {{=}} drops
> everything after the second {{=}}. Should be {{split("=", 2)}} with symmetric
> encoding/decoding. Valueless parameters also trigger the noisy
> {{saveArrayAccess}} WARN with a stack trace.
> h3. Consequence
> For a saga step with e.g.
> {{compensation("seda:cancelOrder?concurrentConsumers=2&size=1000")}} the
> reconstructed URI does not match the registered one, {{verifyRequest()}}
> throws "URI ... is not allowed", and *compensation never runs while the LRA
> coordinator believes it succeeded*. Option values are corrupted the same way
> ({{ACME®ion=EU}} arrives as {{ACME}}; {{a+b}} arrives as {{a b}} because
> {{URLDecoder}} is applied to text that was never encoded).
> This goes unnoticed today only because the documented examples all use plain
> {{direct:}} URIs without parameters.
> h3. Reproducer
> Attached {{LRAUrlEncodingIssueTest.java}} (goes into
> {{components/camel-lra/src/test/java/org/apache/camel/service/lra/}}, no LRA
> coordinator needed, both tests fail on current main):
> * {{testCallbackUrlRoundTrip}}: builds the compensate callback URL exactly
> like {{LRAClient.join()}} and parses it back exactly like
> {{LRASagaRoutes.verifyRequest()}} - values do not round-trip.
> * {{testVerifyRequestAcceptsRegisteredUriWithQueryParams}}: simulates the
> coordinator invoking the compensate callback (CamelHttpQuery fallback path of
> CAMEL-17751) - {{verifyRequest}} rejects the registered compensation URI.
> h3. Suggested fix
> URL-encode key and value in {{LRAUrlBuilder.query()}}, and parse with
> {{split("&")}} / {{split("=", 2)}} plus matching decoding in {{parseQuery}}.
> Found during a broader Saga EIP / camel-lra code review (July 2026).
> _Claude Code on behalf of Croway_
--
This message was sent by Atlassian Jira
(v8.20.10#820010)