This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new d4a8a0b73ccd Upgrade Vert.x to 4.5.27
d4a8a0b73ccd is described below
commit d4a8a0b73ccda49961a0d7a593dbd953d7baac00
Author: James Netherton <[email protected]>
AuthorDate: Thu May 7 15:05:40 2026 +0100
Upgrade Vert.x to 4.5.27
* Upgrade Vert.x to 4.5.27
* CAMEL-23442: Fix vertx-http query string encoding for Undertow 2.4.0.Final
Undertow 2.4.0.Final introduced a strict HTTP parser (commit 14072a2f4)
for CVE fixes that rejects requests from Vert.x WebClient's requestAbs()
API.
Changes:
- Use requestAbs() only when proxy is configured (proxies require absolute
URLs)
- Use request() for direct connections to work with Undertow's strict parser
- Ensure path always starts with "/" (required by strict parser)
- Use RFC1738 encoding (encode()) instead of encodeHttpURI() to properly
encode brackets [, ] and other unsafe characters
- Build URI once to avoid decode/re-encode cycles
- Fix testQueryStringUnsafeCharactersFromHttpUriHeader to use HTTP_QUERY
header instead of embedding unsafe characters in URI string
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
---
.../vertx/http/DefaultVertxHttpBinding.java | 54 ++++++++++----------
.../component/vertx/http/VertxHttpHelper.java | 57 ++++++++++++----------
.../vertx/http/VertxHttpQueryStringTest.java | 7 +--
parent/pom.xml | 2 +-
4 files changed, 61 insertions(+), 59 deletions(-)
diff --git
a/components/camel-vertx/camel-vertx-http/src/main/java/org/apache/camel/component/vertx/http/DefaultVertxHttpBinding.java
b/components/camel-vertx/camel-vertx-http/src/main/java/org/apache/camel/component/vertx/http/DefaultVertxHttpBinding.java
index 8b76a47888ca..d16cb2a0dbfe 100644
---
a/components/camel-vertx/camel-vertx-http/src/main/java/org/apache/camel/component/vertx/http/DefaultVertxHttpBinding.java
+++
b/components/camel-vertx/camel-vertx-http/src/main/java/org/apache/camel/component/vertx/http/DefaultVertxHttpBinding.java
@@ -40,35 +40,24 @@ import org.apache.camel.spi.HeaderFilterStrategy;
import org.apache.camel.support.ExchangeHelper;
import org.apache.camel.util.IOHelper;
import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.URISupport;
import static
org.apache.camel.component.vertx.http.VertxHttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT;
public class DefaultVertxHttpBinding implements VertxHttpBinding {
- private volatile Map<String, Object> defaultQueryParams;
-
@Override
public HttpRequest<Buffer> prepareHttpRequest(VertxHttpEndpoint endpoint,
Exchange exchange) throws Exception {
VertxHttpConfiguration configuration = endpoint.getConfiguration();
Message message = exchange.getMessage();
- // Resolve query string from the HTTP_QUERY header or default to those
provided on the endpoint HTTP URI
- String queryString = VertxHttpHelper.resolveQueryString(exchange,
endpoint);
- Map<String, Object> queryParams = null;
- if (ObjectHelper.isEmpty(queryString)) {
- // use default query string from endpoint configuration
- queryString = configuration.getHttpUri().getQuery();
- if (defaultQueryParams == null) {
- defaultQueryParams = URISupport.parseQuery(queryString);
- }
- queryParams = defaultQueryParams;
- }
+ // Resolve the URI to use which includes query string (similar to
camel-http approach)
+ // Query string is already encoded in resolveHttpURI to avoid
decode/re-encode issues
+ URI uri = VertxHttpHelper.resolveHttpURI(exchange, endpoint);
// Determine the HTTP method to use if not specified in the
HTTP_METHOD header
HttpMethod method = message.getHeader(VertxHttpConstants.HTTP_METHOD,
configuration.getHttpMethod(), HttpMethod.class);
if (method == null) {
- if (ObjectHelper.isNotEmpty(queryString)) {
+ if (ObjectHelper.isNotEmpty(uri.getQuery())) {
method = HttpMethod.GET;
} else if (message.getBody() != null) {
method = HttpMethod.POST;
@@ -77,24 +66,31 @@ public class DefaultVertxHttpBinding implements
VertxHttpBinding {
}
}
- // Resolve the URI to use which is either a combination of headers
HTTP_URI & HTTP_PATH or the HTTP URI configured on the endpoint
- URI uri = VertxHttpHelper.resolveHttpURI(exchange, endpoint);
-
+ // Use the complete URI string (with query string already encoded)
+ // This avoids the decode/re-encode cycle that causes issues with
strict HTTP parsers
WebClient webClient = endpoint.getWebClient();
HttpRequest<Buffer> request;
- if (uri.getPort() != -1) {
- request = webClient.request(method, uri.getPort(), uri.getHost(),
uri.getPath());
- } else {
- request = webClient.requestAbs(method, uri.toString());
- }
- // Configure query params
- if (ObjectHelper.isNotEmpty(queryString)) {
- if (queryParams == null) {
- queryParams = URISupport.parseQuery(queryString);
+ // When using a proxy, use requestAbs() with the full absolute URL.
For direct requests (no proxy), use request()
+ if (ObjectHelper.isNotEmpty(configuration.getProxyHost())) {
+ // Proxy mode - use absolute URL
+ request = webClient.requestAbs(method, uri.toString());
+ } else {
+ // Direct mode - use host/port/path to work with HTTP servers with
strict request parsers
+ String pathAndQuery = uri.getRawPath();
+ if (ObjectHelper.isEmpty(pathAndQuery)) {
+ pathAndQuery = "/";
}
- for (Map.Entry<String, Object> entry : queryParams.entrySet()) {
- request.addQueryParam(entry.getKey(),
entry.getValue().toString());
+ if (uri.getRawQuery() != null) {
+ pathAndQuery = pathAndQuery + "?" + uri.getRawQuery();
+ }
+
+ if (uri.getPort() != -1) {
+ request = webClient.request(method, uri.getPort(),
uri.getHost(), pathAndQuery);
+ } else {
+ // Default ports: 80 for http, 443 for https
+ int port = "https".equals(uri.getScheme()) ? 443 : 80;
+ request = webClient.request(method, port, uri.getHost(),
pathAndQuery);
}
}
diff --git
a/components/camel-vertx/camel-vertx-http/src/main/java/org/apache/camel/component/vertx/http/VertxHttpHelper.java
b/components/camel-vertx/camel-vertx-http/src/main/java/org/apache/camel/component/vertx/http/VertxHttpHelper.java
index d4641f029559..dda45bad5d44 100644
---
a/components/camel-vertx/camel-vertx-http/src/main/java/org/apache/camel/component/vertx/http/VertxHttpHelper.java
+++
b/components/camel-vertx/camel-vertx-http/src/main/java/org/apache/camel/component/vertx/http/VertxHttpHelper.java
@@ -52,31 +52,6 @@ public final class VertxHttpHelper {
// Utility class
}
- /**
- * Resolves a HTTP URI query string from the given exchange message headers
- */
- public static String resolveQueryString(Exchange exchange,
VertxHttpEndpoint endpoint) throws URISyntaxException {
- Message message = exchange.getMessage();
- String queryString = (String)
message.removeHeader(Exchange.REST_HTTP_QUERY);
- if (ObjectHelper.isEmpty(queryString)) {
- queryString = message.getHeader(VertxHttpConstants.HTTP_QUERY,
String.class);
- }
-
- String uriString = null;
- if (!endpoint.getConfiguration().isBridgeEndpoint()) {
- uriString = message.getHeader(VertxHttpConstants.HTTP_URI,
String.class);
- uriString =
exchange.getContext().resolvePropertyPlaceholders(uriString);
- }
-
- if (ObjectHelper.isNotEmpty(uriString)) {
- uriString = UnsafeUriCharactersEncoder.encodeHttpURI(uriString);
- URI uri = new URI(uriString);
- queryString = uri.getQuery();
- }
-
- return queryString;
- }
-
/**
* Resolves a HTTP URI and path string from the given exchange message
headers
*/
@@ -111,7 +86,37 @@ public final class VertxHttpHelper {
}
}
- uri = UnsafeUriCharactersEncoder.encodeHttpURI(uri);
+ // Get query string from headers (rest producer may provide an
override)
+ String queryString = (String)
message.removeHeader(Exchange.REST_HTTP_QUERY);
+ if (queryString == null) {
+ queryString = message.getHeader(VertxHttpConstants.HTTP_QUERY,
String.class);
+ }
+
+ // Parse URI to check for existing query string
+ URI tempUri = new URI(uri);
+ if (queryString == null) {
+ queryString = tempUri.getRawQuery();
+ }
+ if (queryString == null && endpoint.getConfiguration().getHttpUri() !=
null) {
+ queryString =
endpoint.getConfiguration().getHttpUri().getRawQuery();
+ }
+
+ // Build the complete URI string with encoded query (similar to
camel-http approach)
+ // Encode the full URI once to avoid double-encoding
+ if (queryString != null) {
+ // Build URI string without query first
+ String baseUri = tempUri.toString();
+ int queryIndex = baseUri.indexOf('?');
+ if (queryIndex != -1) {
+ baseUri = baseUri.substring(0, queryIndex);
+ }
+ // Encode query string using RFC1738 encoding (includes [, ], #,
etc.)
+ // This is stricter than encodeHttpURI() which only encodes a
subset
+ queryString = UnsafeUriCharactersEncoder.encode(queryString);
+ uri = baseUri + "?" + queryString;
+ } else {
+ uri = UnsafeUriCharactersEncoder.encode(uri);
+ }
return new URI(uri);
}
diff --git
a/components/camel-vertx/camel-vertx-http/src/test/java/org/apache/camel/component/vertx/http/VertxHttpQueryStringTest.java
b/components/camel-vertx/camel-vertx-http/src/test/java/org/apache/camel/component/vertx/http/VertxHttpQueryStringTest.java
index d1cd764a29f9..18cb112acc04 100644
---
a/components/camel-vertx/camel-vertx-http/src/test/java/org/apache/camel/component/vertx/http/VertxHttpQueryStringTest.java
+++
b/components/camel-vertx/camel-vertx-http/src/test/java/org/apache/camel/component/vertx/http/VertxHttpQueryStringTest.java
@@ -28,13 +28,13 @@ public class VertxHttpQueryStringTest extends
VertxHttpTestSupport {
@Test
public void testQueryStringPropertyPlaceholder() {
String result = template.requestBody(getProducerUri() +
"?os={{sys:os.name}}", null, String.class);
- assertEquals("os=" + System.getProperty("os.name"),
result.replaceAll("%20", " "));
+ assertEquals("os=" + System.getProperty("os.name").replace(' ', '+'),
result);
}
@Test
public void testQueryStringFromHttpUriHeader() {
String result = template.requestBody(getProducerUri() +
"?os={{sys:os.name}}", null, String.class);
- assertEquals("os=" + System.getProperty("os.name"),
result.replaceAll("%20", " "));
+ assertEquals("os=" + System.getProperty("os.name").replace(' ', '+'),
result);
}
@Test
@@ -64,7 +64,8 @@ public class VertxHttpQueryStringTest extends
VertxHttpTestSupport {
.setBody(header(Exchange.HTTP_QUERY));
from("direct:start")
- .setHeader(Exchange.HTTP_URI,
constant(getTestServerUrl() + "?foo=bar#^[]"))
+ .setHeader(Exchange.HTTP_URI,
constant(getTestServerUrl()))
+ .setHeader(Exchange.HTTP_QUERY,
constant("foo=bar#^[]"))
.to(getProducerUri());
}
};
diff --git a/parent/pom.xml b/parent/pom.xml
index 96681c349d85..1cdb4ba7ebdb 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -514,7 +514,7 @@
<vavr-version>1.0.0</vavr-version>
<velocity-tools-version>3.1</velocity-tools-version>
<velocity-version>2.4.1</velocity-version>
- <vertx-version>4.5.26</vertx-version>
+ <vertx-version>4.5.27</vertx-version>
<weaviate-client-version>5.5.0</weaviate-client-version>
<web3j-version>5.0.0</web3j-version>
<web3j-quorum-version>4.10.0</web3j-quorum-version>