This is an automated email from the ASF dual-hosted git repository.
davsclaus 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 69f5b41527db CAMEL-25635: camel-platform-http-vertx - the charset
parameter of the request Content-Type is only recognized in lower case (#27853)
69f5b41527db is described below
commit 69f5b41527dbe626d612404a71c01f150a52ec2c
Author: allthingssecurity <[email protected]>
AuthorDate: Thu Oct 15 17:31:36 2026 +0530
CAMEL-25635: camel-platform-http-vertx - the charset parameter of the
request Content-Type is only recognized in lower case (#27853)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
.../http/vertx/VertxPlatformHttpConsumer.java | 19 ++++-
.../vertx/VertxPlatformHttpRequestCharsetTest.java | 99 ++++++++++++++++++++++
.../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc | 8 ++
3 files changed, 125 insertions(+), 1 deletion(-)
diff --git
a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java
b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java
index 4735af73e171..1f725df7b368 100644
---
a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java
+++
b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java
@@ -36,6 +36,7 @@ import io.vertx.core.http.CookieSameSite;
import io.vertx.core.http.HttpMethod;
import io.vertx.ext.auth.User;
import io.vertx.ext.web.FileUpload;
+import io.vertx.ext.web.ParsedHeaderValue;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.TimeoutHandler;
@@ -61,7 +62,9 @@ import org.apache.camel.spi.RestRegistry.RestService;
import org.apache.camel.support.DefaultConsumer;
import org.apache.camel.support.PluginHelper;
import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.IOHelper;
import org.apache.camel.util.MimeTypeHelper;
+import org.apache.camel.util.ObjectHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -487,11 +490,25 @@ public class VertxPlatformHttpConsumer extends
DefaultConsumer
exchange.getMessage().removeHeader("Proxy-Connection");
}
+ /**
+ * The charset parameter of the request Content-Type, whose name is
case-insensitive (RFC 9110), or null when there
+ * is none or its value is empty ({@code charset=}, {@code charset=""}),
as in UndertowHelper and NettyHttpHelper.
+ */
+ private static String charsetParameter(ParsedHeaderValue contentType) {
+ for (Map.Entry<String, String> parameter :
contentType.parameters().entrySet()) {
+ if ("charset".equalsIgnoreCase(parameter.getKey())) {
+ String name = IOHelper.normalizeCharset(parameter.getValue());
+ return ObjectHelper.isEmpty(name) ? null : name;
+ }
+ }
+ return null;
+ }
+
protected Future<Void> processHttpRequest(Exchange exchange,
RoutingContext ctx) {
// reuse existing http message if pooled
Message in = initializeHttpMessage(exchange, ctx);
- final String charset =
ctx.parsedHeaders().contentType().parameter("charset");
+ final String charset =
charsetParameter(ctx.parsedHeaders().contentType());
if (charset != null) {
exchange.setProperty(ExchangePropertyKey.CHARSET_NAME, charset);
in.setHeader(Exchange.HTTP_CHARACTER_ENCODING, charset);
diff --git
a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpRequestCharsetTest.java
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpRequestCharsetTest.java
new file mode 100644
index 000000000000..cbd3d4cfc3fd
--- /dev/null
+++
b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpRequestCharsetTest.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.platform.http.vertx;
+
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static java.nio.charset.StandardCharsets.ISO_8859_1;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * The charset parameter of the request Content-Type is read whatever the case
of its name (RFC 9110, 5.6.6), and an
+ * empty charset parameter counts as no charset (CAMEL-25355).
+ */
+class VertxPlatformHttpRequestCharsetTest {
+
+ private static final String TEXT = "Grüße aus Köln";
+
+ private CamelContext context;
+
+ @BeforeEach
+ void setUp() throws Exception {
+ context = VertxPlatformHttpEngineTest.createCamelContext();
+ context.addRoutes(new RouteBuilder() {
+ @Override
+ public void configure() {
+ // decodes the request in its charset and answers in UTF-8
+ from("platform-http:/decode")
+ .convertBodyTo(String.class)
+ .setHeader(Exchange.CONTENT_TYPE,
constant("text/plain; charset=UTF-8"));
+ }
+ });
+ VertxPlatformHttpEngineTest.startCamelContext(context);
+ }
+
+ @AfterEach
+ void tearDown() {
+ context.stop();
+ }
+
+ @Test
+ void testRequestCharsetParameterInUpperCase() throws Exception {
+ HttpResponse<byte[]> response = post("text/plain; Charset=ISO-8859-1",
TEXT.getBytes(ISO_8859_1));
+
+ assertEquals(200, response.statusCode());
+ assertArrayEquals(TEXT.getBytes(UTF_8), response.body());
+ }
+
+ @Test
+ void testEmptyRequestCharsetParameter() throws Exception {
+ // no charset: the body is decoded with the default charset (UTF-8)
instead of failing on Charset.forName("")
+ HttpResponse<byte[]> response = post("text/plain; charset=",
TEXT.getBytes(UTF_8));
+
+ assertEquals(200, response.statusCode());
+ assertArrayEquals(TEXT.getBytes(UTF_8), response.body());
+ }
+
+ @Test
+ void testEmptyQuotedRequestCharsetParameterFollowedByAnotherParameter()
throws Exception {
+ HttpResponse<byte[]> response = post("text/plain; charset=\"\";
format=flowed", TEXT.getBytes(UTF_8));
+
+ assertEquals(200, response.statusCode());
+ assertArrayEquals(TEXT.getBytes(UTF_8), response.body());
+ }
+
+ private HttpResponse<byte[]> post(String contentType, byte[] body) throws
Exception {
+ VertxPlatformHttpServer server =
context.hasService(VertxPlatformHttpServer.class);
+ HttpRequest request =
HttpRequest.newBuilder(URI.create("http://localhost:" + server.getPort() +
"/decode"))
+ .header("Content-Type", contentType)
+ .POST(HttpRequest.BodyPublishers.ofByteArray(body))
+ .build();
+ return HttpClient.newHttpClient().send(request,
HttpResponse.BodyHandlers.ofByteArray());
+ }
+}
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index 0942e3621447..cfe3340e54d4 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -350,6 +350,14 @@ with `OAuthHelper.validateOAuthToken` from camel-support
instead.
For any other message, such as one from camel-undertow, the processors keep
reading the message headers, but leave out
a value that also appears in the query string of the request.
+=== camel-platform-http-vertx - the charset parameter of the request
Content-Type in any case
+
+The consumer now reads the charset parameter of the request `Content-Type`
whatever the case of its name, as
+camel-undertow and camel-netty-http do: a body sent with `Content-Type:
text/plain; Charset=ISO-8859-1` is decoded as
+ISO-8859-1 and `CamelCharsetName` is set. Before, only `charset=` in lower
case was read and such a body was decoded
+as UTF-8. An empty charset parameter (`charset=` or `charset=""`) now counts
as no charset, as in camel-undertow,
+camel-netty-http and camel-http-common (CAMEL-25355); before, converting the
body to a String failed with 500.
+
=== camel-report-maven-plugin - Java routes are read with the Java DSL parser
The `validate` and `route-coverage` goals read Java routes with the Java DSL
parser of camel-java-io instead of