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:55 UTC
(camel) 01/01: [backport camel-4.22.x] CAMEL-24409: keep binary bodies intact in rest client request validation
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.