You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2026/09/03 08:36:54 UTC
(camel) branch backport/26024-to-camel-4.22.x created (now 566dc3f053a2)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a change to branch backport/26024-to-camel-4.22.x
in repository https://gitbox.apache.org/repos/asf/camel.git
at 566dc3f053a2 [backport camel-4.22.x] CAMEL-24409: keep binary bodies intact in rest client request validation
This branch includes the following new commits:
new 566dc3f053a2 [backport camel-4.22.x] CAMEL-24409: keep binary bodies intact in rest client request validation
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(camel) 01/01: [backport camel-4.22.x] CAMEL-24409: keep binary bodies intact in rest client request validation
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch backport/26024-to-camel-4.22.x
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 566dc3f053a2ccea74a37b39a2101902b7b4eca4
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Sep 3 10:35:41 2026 +0200
[backport camel-4.22.x] CAMEL-24409: keep binary bodies intact in rest client request validation
Checking that a required body is present read the body as a String and wrote
that String back onto the message, which corrupted binary payloads such as
application/octet-stream. extractBodyAsString already leaves the body as a
re-readable StreamCache, so the write back was not needed to keep the body
readable, only to lose the bytes.
(cherry picked from commit cfa4c3692956969195835017fae105514464525a)
Co-authored-by: Claude Opus 5 <no...@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
Signed-off-by: Claus Ibsen <cl...@gmail.com>
---
.../jetty/rest/RestJettyRequiredBodyTest.java | 23 ++++++++++++++++++++++
.../DefaultRestClientRequestValidator.java | 8 ++++----
.../ROOT/pages/camel-4x-upgrade-guide-4_22.adoc | 7 +++++++
3 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyRequiredBodyTest.java b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyRequiredBodyTest.java
index 093bbb58f1f7..2616e574a7e9 100644
--- a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyRequiredBodyTest.java
+++ b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyRequiredBodyTest.java
@@ -26,11 +26,15 @@ import org.apache.camel.model.rest.RestParamType;
import org.junit.jupiter.api.Test;
import static org.apache.camel.test.junit6.TestSupport.assertIsInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class RestJettyRequiredBodyTest extends BaseJettyTest {
+ // bytes that are not valid UTF-8, so they would be replaced if the body was turned into a String
+ private static final byte[] BINARY_BODY = { 0x00, 0x01, (byte) 0xFF, (byte) 0xFE, (byte) 0x80, 0x7F, (byte) 0xC3, 0x28 };
+
@Test
public void testJettyValid() {
String out = fluentTemplate.withHeader(Exchange.CONTENT_TYPE, "application/json")
@@ -70,6 +74,18 @@ public class RestJettyRequiredBodyTest extends BaseJettyTest {
assertEquals("The request body is missing.", cause.getResponseBody());
}
+ @Test
+ public void testJettyBinaryBodyNotCorrupted() {
+ byte[] out = fluentTemplate.withHeader(Exchange.CONTENT_TYPE, "application/octet-stream")
+ .withHeader("Accept", "application/octet-stream")
+ .withHeader(Exchange.HTTP_METHOD, "post")
+ .withBody(BINARY_BODY)
+ .to("http://localhost:" + getPort() + "/users/123/upload")
+ .request(byte[].class);
+
+ assertArrayEquals(BINARY_BODY, out);
+ }
+
@Override
protected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
@@ -85,6 +101,13 @@ public class RestJettyRequiredBodyTest extends BaseJettyTest {
.name("body").required(true).type(RestParamType.body)
.endParam().to("direct:update");
from("direct:update").setBody(constant("{ \"status\": \"ok\" }"));
+
+ // a binary service that echoes back what it received
+ rest("/users/").post("{id}/upload").consumes("application/octet-stream")
+ .produces("application/octet-stream").param()
+ .name("body").required(true).type(RestParamType.body)
+ .endParam().to("direct:upload");
+ from("direct:upload").setBody(bodyAs(byte[].class));
}
};
}
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/processor/DefaultRestClientRequestValidator.java b/core/camel-support/src/main/java/org/apache/camel/support/processor/DefaultRestClientRequestValidator.java
index a9add96dfeaa..af9ca20a755e 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/processor/DefaultRestClientRequestValidator.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/processor/DefaultRestClientRequestValidator.java
@@ -74,11 +74,11 @@ public class DefaultRestClientRequestValidator implements RestClientRequestValid
Object body = exchange.getMessage().getBody();
if (validationContext.requiredBody()) {
// the body is required, so we need to know if we have a body or not
- // so force reading the body as a String which we can work with
+ // so force reading the body as a String which we can work with.
+ // extractBodyAsString uses stream caching so the message body stays re-readable,
+ // and the body is deliberately not replaced with the String as that would
+ // corrupt binary payloads such as application/octet-stream
body = MessageHelper.extractBodyAsString(exchange.getIn());
- if (ObjectHelper.isNotEmpty(body)) {
- exchange.getIn().setBody(body);
- }
if (ObjectHelper.isEmpty(body)) {
// this is a bad request, the client did not include a message body
return new ValidationError(400, "The request body is missing.");
diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
index 435153a8a2df..094508581eee 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
@@ -1814,3 +1814,10 @@ The `backOffMaxAttempts` option now bounds the attempts to start the delegated c
The retry task previously also carried the default five second duration of its budget, which ended the
task before the second attempt for any `backOffDelay` at or above the default of five seconds. A delegate
that fails to start is therefore retried for longer than before, up to `backOffMaxAttempts` times.
+
+=== camel-core - REST client request validation and binary bodies
+
+When `clientRequestValidation` is enabled and the REST service declares a required body, the incoming
+message body is no longer replaced with a `String` version of itself. That conversion corrupted binary
+payloads such as `application/octet-stream`. The body is still read to check that it is present, using
+stream caching so it stays re-readable, but it now keeps its original type.