This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch fix/CAMEL-25188 in repository https://gitbox.apache.org/repos/asf/camel.git
commit 9b52046ca7343c5b6d61b6bb5d91673c6698a891 Author: Claus Ibsen <[email protected]> AuthorDate: Wed Sep 30 15:32:47 2026 +0200 CAMEL-25188: camel-util - URISupport.normalizeUri writes a space in a query value as + in the fast path too Since CAMEL-24524 the fast path wrote a space as %20 while the complex path writes +, so normalizing a normalized uri changed it, and the same endpoint written as a+b or a%20b got two endpoint keys. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../java/org/apache/camel/util/URISupport.java | 3 ++ .../java/org/apache/camel/util/URISupportTest.java | 34 ++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java b/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java index 25250ff857b6..0f97643e11e6 100644 --- a/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java +++ b/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java @@ -955,6 +955,9 @@ public final class URISupport { // characters in a URI query per RFC 3986 - UnsafeUriCharactersEncoder does not escape them // as it is also used outside of this query-value context String encoded = UnsafeUriCharactersEncoder.encode(value).replace("&", "%26").replace("=", "%3D"); + // a space as +, as the complex normalizer (createQueryString) writes it, so normalizing a normalized + // uri gives the same uri; the fast parser only takes uris without %, so %20 here is always a space + encoded = encoded.replace("%20", "+"); sb.append(encoded); } } diff --git a/core/camel-util/src/test/java/org/apache/camel/util/URISupportTest.java b/core/camel-util/src/test/java/org/apache/camel/util/URISupportTest.java index 4cd22a9b2bf0..a6e32cc42fe3 100644 --- a/core/camel-util/src/test/java/org/apache/camel/util/URISupportTest.java +++ b/core/camel-util/src/test/java/org/apache/camel/util/URISupportTest.java @@ -148,6 +148,40 @@ public class URISupportTest { assertEquals("http://www.google.com?q=S%C3%B8ren+Hansen", out); } + @Test + public void testNormalizeSpaceTheSameInEverySpelling() throws Exception { + // CAMEL-25188: the fast and the complex normalizer both write a space in a value as + + assertThat(URISupport.normalizeUri("log:foo?marker=a+b")).isEqualTo("log://foo?marker=a+b"); + assertThat(URISupport.normalizeUri("log:foo?marker=a%20b")).isEqualTo("log://foo?marker=a+b"); + assertThat(URISupport.normalizeUri("log:foo?marker=a b")).isEqualTo("log://foo?marker=a+b"); + assertThat(URISupport.normalizeUri("log:foo?showAll=true&marker=a+b")) + .isEqualTo("log://foo?marker=a+b&showAll=true"); + assertThat(URISupport.normalizeUri("log:foo?marker=a++b")).isEqualTo("log://foo?marker=a++b"); + } + + @Test + public void testNormalizeTwiceGivesTheSameUri() throws Exception { + // CAMEL-25188: a normalized uri normalizes to itself, so endpoint keys and lookups agree + String[] uris = { + "http://localhost:8080/foo?a=1&b=2", + "http://localhost:8080/foo?b=hello world&a=1", + "http://localhost:8080/foo?q=a+b", + "http://localhost:8080/foo?q=a%20b", + "http://localhost:8080/foo?q=a+b&x=1", + "ftp://[email protected]:21/dir?password=se+cret&binary=true", + "ftp://[email protected]:21/dir?password=RAW(se+cret)&binary=true", + "log:foo?level=INFO&showAll=true", + "timer:tick?period=1s&delay=2s", + "direct:start?b=\u00f8&a=1", + "file:target/in?include=.*\\.txt&noop=true", + "http://h/p?x=a&x=b&y=1", + "mock:a?b=x+y+z&a=1" }; + for (String uri : uris) { + String once = URISupport.normalizeUri(uri); + assertThat(URISupport.normalizeUri(once)).as("normalizing %s twice", uri).isEqualTo(once); + } + } + @Test public void testParseParametersURLEncodedValue() throws Exception { String out = URISupport.normalizeUri("http://www.google.com?q=S%C3%B8ren%20Hansen");
