This is an automated email from the ASF dual-hosted git repository.
fmariani pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git
The following commit(s) were added to refs/heads/main by this push:
new 6f9d1b650a2 CAMEL-23320: useReaderForPayload corrupts non-text request
bodies under Spring Boot's default UTF-8 charset (#1747)
6f9d1b650a2 is described below
commit 6f9d1b650a247cad5f8365b8c78dc1b130b25ebc
Author: Federico Mariani <[email protected]>
AuthorDate: Wed Apr 15 11:14:19 2026 +0200
CAMEL-23320: useReaderForPayload corrupts non-text request bodies under
Spring Boot's default UTF-8 charset (#1747)
* CAMEL-23320: Fix platform-http binary data corruption and align
useStreaming with Vert.x
* CAMEL-23320: Fix flaky request timeout test by widening timeout margin
* Adds reproducer for CAMEL-23320
---------
Co-authored-by: Marco Carletti <[email protected]>
---
.../http/springboot/PlatformHttpMessage.java | 21 ++--
.../springboot/SpringBootPlatformHttpBinding.java | 26 ++++-
.../springboot/SpringBootPlatformHttpConsumer.java | 8 +-
.../springboot/PlatformHttpBinaryUploadTest.java | 128 ++++++++++++++++++++
.../http/springboot/PlatformHttpStreamingTest.java | 82 ++++++++++++-
.../SpringBootPlatformHttpCertificationTest.java | 1 -
...gBootPlatformHttpHeaderFilterStrategyTest.java} | 71 +++++++-----
.../SpringBootPlatformHttpRequestTimeoutTest.java | 2 +-
.../SpringBootPlatformHttpResponseCodeTest.java | 129 +++++++++++++++++++++
.../component/platform/http/springboot/example.pdf | Bin 0 -> 553 bytes
10 files changed, 423 insertions(+), 45 deletions(-)
diff --git
a/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/PlatformHttpMessage.java
b/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/PlatformHttpMessage.java
index e106bb554ce..e22f7a57269 100644
---
a/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/PlatformHttpMessage.java
+++
b/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/PlatformHttpMessage.java
@@ -33,6 +33,7 @@ public class PlatformHttpMessage extends DefaultMessage {
private HttpServletResponse response;
private HttpBinding binding;
private boolean requestRead;
+ private boolean streaming;
public PlatformHttpMessage(Exchange exchange, HttpBinding binding,
HttpServletRequest request,
HttpServletResponse response) {
@@ -41,12 +42,12 @@ public class PlatformHttpMessage extends DefaultMessage {
}
public PlatformHttpMessage(HttpServletRequest request, HttpServletResponse
response, Exchange exchange,
- HttpBinding binding, boolean requestRead) {
+ HttpBinding binding, boolean streaming) {
super(exchange);
this.request = request;
this.response = response;
this.binding = binding;
- this.requestRead = requestRead;
+ this.streaming = streaming;
}
public void init(Exchange exchange, HttpBinding binding,
HttpServletRequest request, HttpServletResponse response) {
@@ -62,12 +63,16 @@ public class PlatformHttpMessage extends DefaultMessage {
if (flag != null && flag) {
this.setHeader("CamelSkipWwwFormUrlEncoding", Boolean.TRUE);
}
- // we need to favor using stream cache so the body can be re-read
later when routing the message
- StreamCache newBody =
camelContext.getTypeConverter().tryConvertTo(StreamCache.class,
- exchange, getBody());
- if (newBody != null) {
- setBody(newBody);
+ if (streaming) {
+ // when streaming, use CachedOutputStream via HttpHelper for
disk-spoolable large payload support
+ // the body will be an InputStreamCache (re-readable StreamCache)
+ StreamCache newBody =
camelContext.getTypeConverter().tryConvertTo(StreamCache.class,
+ exchange, getBody());
+ if (newBody != null) {
+ setBody(newBody);
+ }
}
+ // when not streaming, the body is already a byte[] (re-readable, no
conversion needed)
binding.readRequest(request, this);
}
@@ -105,7 +110,7 @@ public class PlatformHttpMessage extends DefaultMessage {
}
public PlatformHttpMessage newInstance() {
- PlatformHttpMessage answer = new PlatformHttpMessage(this.request,
this.response, this.getExchange(), this.binding, this.requestRead);
+ PlatformHttpMessage answer = new PlatformHttpMessage(this.request,
this.response, this.getExchange(), this.binding, this.streaming);
if (answer.camelContext == null) {
answer.setCamelContext(this.camelContext);
}
diff --git
a/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpBinding.java
b/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpBinding.java
index 7e92af3f625..a69a8ea151f 100644
---
a/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpBinding.java
+++
b/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpBinding.java
@@ -64,6 +64,7 @@ import java.util.UUID;
public class SpringBootPlatformHttpBinding extends DefaultHttpBinding {
private static final Logger LOG =
LoggerFactory.getLogger(SpringBootPlatformHttpBinding.class);
+ private boolean streaming;
private static final String CONTENT_TYPE_FORM_URLENCODED =
"application/x-www-form-urlencoded";
private static final List<Method> METHODS_WITH_BODY_ALLOWED =
List.of(Method.POST,
Method.PUT, Method.PATCH, Method.DELETE);
@@ -149,6 +150,10 @@ public class SpringBootPlatformHttpBinding extends
DefaultHttpBinding {
}
}
+ public void setStreaming(boolean streaming) {
+ this.streaming = streaming;
+ }
+
public Object parseBody(HttpServletRequest request, Message message)
throws IOException {
if (request instanceof StandardMultipartHttpServletRequest ||
// In case of Spring FormContentFilter
@@ -156,7 +161,24 @@ public class SpringBootPlatformHttpBinding extends
DefaultHttpBinding {
return null;
}
- return super.parseBody(request, message);
+ int len = request.getContentLength();
+ if (len == 0) {
+ return null;
+ }
+
+ if (streaming) {
+ // use CachedOutputStream for disk-spoolable large payload support
(like Vert.x streaming)
+ return super.parseBody(request, message);
+ } else {
+ // read entire body into byte[] for fast in-memory access (like
Vert.x Buffer)
+ if (len > 0) {
+ // known content-length: single allocation, no internal array
copies
+ return request.getInputStream().readNBytes(len);
+ }
+ // unknown content-length (-1): fall back to incremental read
+ byte[] body = request.getInputStream().readAllBytes();
+ return body.length == 0 ? null : body;
+ }
}
@Override
@@ -169,7 +191,7 @@ public class SpringBootPlatformHttpBinding extends
DefaultHttpBinding {
private static void populateMultiFormData(HttpServletRequest request,
Message message) {
if (((PlatformHttpEndpoint)
message.getExchange().getFromEndpoint()).isPopulateBodyWithForm() &&
METHODS_WITH_BODY_ALLOWED.contains(Method.valueOf(request.getMethod())) &&
- (message.getBody() instanceof StreamCache ||
+ (message.getBody() instanceof StreamCache || message.getBody()
instanceof byte[] ||
(message.getBody() == null &&
!"POST".equals(request.getMethod()))) &&
request.getContentType() != null &&
request.getContentType().contains(CONTENT_TYPE_FORM_URLENCODED)) {
diff --git
a/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpConsumer.java
b/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpConsumer.java
index 0755375c58b..2b86c7878d0 100644
---
a/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpConsumer.java
+++
b/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpConsumer.java
@@ -54,11 +54,12 @@ public class SpringBootPlatformHttpConsumer extends
DefaultConsumer implements P
public SpringBootPlatformHttpConsumer(PlatformHttpEndpoint endpoint,
Processor processor) {
super(endpoint, processor);
- this.binding = new SpringBootPlatformHttpBinding();
+ SpringBootPlatformHttpBinding httpBinding = new
SpringBootPlatformHttpBinding();
+ httpBinding.setStreaming(endpoint.isUseStreaming());
+ this.binding = httpBinding;
this.binding.setHeaderFilterStrategy(endpoint.getHeaderFilterStrategy());
this.binding.setMuteException(endpoint.isMuteException());
this.binding.setFileNameExtWhitelist(endpoint.getFileNameExtWhitelist());
- this.binding.setUseReaderForPayload(!endpoint.isUseStreaming());
this.handleWriteResponseError = endpoint.isHandleWriteResponseError();
this.executor = Executors.newSingleThreadExecutor();
}
@@ -117,7 +118,8 @@ public class SpringBootPlatformHttpConsumer extends
DefaultConsumer implements P
Exchange exchange = createExchange(true);
exchange.setPattern(ExchangePattern.InOut);
HttpHelper.setCharsetFromContentType(request.getContentType(),
exchange);
- PlatformHttpMessage msg = new PlatformHttpMessage(request, response,
exchange,binding, false);
+ boolean streaming = getEndpoint().isUseStreaming();
+ PlatformHttpMessage msg = new PlatformHttpMessage(request, response,
exchange, binding, streaming);
exchange.setIn(msg);
msg.init(exchange, binding, request, response);
String contextPath = getEndpoint().getPath();
diff --git
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/PlatformHttpBinaryUploadTest.java
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/PlatformHttpBinaryUploadTest.java
new file mode 100644
index 00000000000..40e2c612c81
--- /dev/null
+++
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/PlatformHttpBinaryUploadTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.springboot;
+
+import io.restassured.RestAssured;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit6.CamelSpringBootTest;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import
org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import
org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
+import org.springframework.security.web.SecurityFilterChain;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static io.restassured.RestAssured.given;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests binary file upload through platform-http REST DSL.
+ * Reproducer for <a
href="https://issues.apache.org/jira/browse/CAMEL-23320">CAMEL-23320</a>:
+ * binary data corruption caused by Reader-based parsing in non-streaming mode.
+ */
+@EnableAutoConfiguration
+@CamelSpringBootTest
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { CamelAutoConfiguration.class,
+ SpringBootPlatformHttpTest.class,
PlatformHttpBinaryUploadTest.TestConfiguration.class,
+ PlatformHttpComponentAutoConfiguration.class,
SpringBootPlatformHttpAutoConfiguration.class })
+public class PlatformHttpBinaryUploadTest {
+
+ static final String FILE_NAME = "example.pdf";
+ static Path uploadDir;
+
+ @LocalServerPort
+ private int port;
+
+ @BeforeAll
+ public static void createUploadDir() throws IOException {
+ uploadDir = Files.createTempDirectory(Path.of("target"),
"platform-http-upload");
+ }
+
+ @AfterAll
+ public static void cleanUploadDir() throws IOException {
+ Files.deleteIfExists(uploadDir.resolve(FILE_NAME));
+ Files.deleteIfExists(uploadDir);
+ }
+
+ @BeforeEach
+ public void setUp() {
+ RestAssured.port = port;
+ }
+
+ @Test
+ void testBinaryPdfUpload() throws IOException {
+ byte[] pdfBytes =
getClass().getResourceAsStream(FILE_NAME).readAllBytes();
+
+ given()
+ .body(pdfBytes)
+ .contentType("application/pdf")
+ .post("/upload")
+ .then()
+ .statusCode(200);
+
+ Path uploadedFile = uploadDir.resolve(FILE_NAME);
+ assertTrue(Files.exists(uploadedFile), "The uploaded file should
exist");
+ assertArrayEquals(pdfBytes, Files.readAllBytes(uploadedFile), "The PDF
should not be corrupted");
+ }
+
+ @Configuration
+ public static class TestConfiguration {
+
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity http)
throws Exception {
+ http.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
+ .csrf(AbstractHttpConfigurer::disable);
+ return http.build();
+ }
+
+ @Bean
+ public RouteBuilder routeBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ rest().consumes("application/pdf")
+ .post("/upload")
+ .to("direct:upload");
+
+ from("direct:upload")
+ .convertBodyTo(byte[].class)
+ .process(exchange -> {
+ byte[] body =
exchange.getIn().getBody(byte[].class);
+ try (FileOutputStream fos = new
FileOutputStream(
+
uploadDir.resolve(FILE_NAME).toFile())) {
+ fos.write(body);
+ }
+ })
+ .setBody(constant("uploaded"));
+ }
+ };
+ }
+ }
+}
diff --git
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/PlatformHttpStreamingTest.java
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/PlatformHttpStreamingTest.java
index 1d92e987d5a..90499e70fe7 100644
---
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/PlatformHttpStreamingTest.java
+++
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/PlatformHttpStreamingTest.java
@@ -43,6 +43,7 @@ import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.emptyOrNullString;
import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
@EnableAutoConfiguration
@@ -130,7 +131,7 @@ public class PlatformHttpStreamingTest {
.then()
.statusCode(200)
.header("foo", "bar")
- .header("BodyClass", containsString("ReaderCache"))
+ .header("BodyClass", containsString("[B"))
.body(is("foo=bar"));
}
@@ -155,6 +156,73 @@ public class PlatformHttpStreamingTest {
assertEquals(fileContent, Files.readString(output,
StandardCharsets.ISO_8859_1));
}
+ @Test
+ void testNonStreamingWithBinaryData() {
+ byte[] binaryData = new byte[] {0x00, 0x0c, (byte) 0x80, (byte) 0xff,
(byte) 0xfe, 0x0f, 0x0e};
+ byte[] response = given()
+ .body(binaryData)
+ .contentType(ContentType.BINARY)
+ .post("/binaryData")
+ .then()
+ .statusCode(200)
+ .extract().body().asByteArray();
+ assertArrayEquals(binaryData, response);
+ }
+
+ @Test
+ void testStreamingWithBinaryData() {
+ byte[] binaryData = new byte[] {0x00, 0x0c, (byte) 0x80, (byte) 0xff,
(byte) 0xfe, 0x0f, 0x0e};
+ byte[] response = given()
+ .body(binaryData)
+ .contentType(ContentType.BINARY)
+ .post("/streamingBinaryData")
+ .then()
+ .statusCode(200)
+ .extract().body().asByteArray();
+ assertArrayEquals(binaryData, response);
+ }
+
+ @Test
+ void testNonStreamingWithKnownContentLength() {
+ // When Content-Length is known, the optimized readNBytes(len) path is
used
+ // (single byte[] allocation instead of incremental readAllBytes)
+ byte[] largeBody = new byte[8192];
+ for (int i = 0; i < largeBody.length; i++) {
+ largeBody[i] = (byte) (i % 256);
+ }
+ byte[] response = given()
+ .body(largeBody)
+ .contentType(ContentType.BINARY)
+ .post("/binaryData")
+ .then()
+ .statusCode(200)
+ .extract().body().asByteArray();
+ assertArrayEquals(largeBody, response);
+ }
+
+ @Test
+ void testStreamingBodyIsStreamCache() {
+ String requestBody = "streaming body type check";
+ given()
+ .body(requestBody)
+ .post("/streamingBodyType")
+ .then()
+ .statusCode(200)
+ .header("BodyIsStreamCache", "true")
+ .body(is(requestBody));
+ }
+
+ @Test
+ void testNonStreamingBodyIsByteArray() {
+ String requestBody = "non-streaming body type check";
+ given()
+ .body(requestBody)
+ .post("/nonStreamingBodyType")
+ .then()
+ .statusCode(200)
+ .header("BodyIsStreamCache", "false");
+ }
+
@Configuration
public static class TestConfiguration {
@@ -188,6 +256,18 @@ public class PlatformHttpStreamingTest {
.process(exchange ->
exchange.getMessage().setHeader("BodyClass",
exchange.getIn().getBody().getClass().getName()))
.log("Done processing request");
+
+ from("platform-http:/binaryData").log("Done processing
binary request");
+
+
from("platform-http:/streamingBinaryData?useStreaming=true").log("Done
processing streaming binary request");
+ from("platform-http:/streamingBodyType?useStreaming=true")
+ .process(exchange ->
exchange.getMessage().setHeader("BodyIsStreamCache",
+ String.valueOf(exchange.getIn().getBody()
instanceof org.apache.camel.StreamCache)))
+ .log("Done processing streaming body type check");
+ from("platform-http:/nonStreamingBodyType")
+ .process(exchange ->
exchange.getMessage().setHeader("BodyIsStreamCache",
+ String.valueOf(exchange.getIn().getBody()
instanceof org.apache.camel.StreamCache)))
+ .log("Done processing non-streaming body type
check");
}
};
}
diff --git
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCertificationTest.java
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCertificationTest.java
index 8a9b519dacc..0ce16eb0077 100644
---
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCertificationTest.java
+++
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpCertificationTest.java
@@ -312,7 +312,6 @@ public class SpringBootPlatformHttpCertificationTest
extends PlatformHttpBase {
CamelContext camelContext;
@Test
- @Disabled
@DisabledIfSystemProperties({
@DisabledIfSystemProperty(named = "ci.env.name", matches = ".*",
disabledReason = "File too large for CI"),
diff --git
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpRequestTimeoutTest.java
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpHeaderFilterStrategyTest.java
similarity index 58%
copy from
components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpRequestTimeoutTest.java
copy to
components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpHeaderFilterStrategyTest.java
index 789f85c8352..bfbe92d0d2e 100644
---
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpRequestTimeoutTest.java
+++
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpHeaderFilterStrategyTest.java
@@ -16,48 +16,54 @@
*/
package org.apache.camel.component.platform.http.springboot;
+import io.restassured.RestAssured;
import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.http.common.HttpHeaderFilterStrategy;
import org.apache.camel.spring.boot.CamelAutoConfiguration;
import org.apache.camel.test.spring.junit6.CamelSpringBootTest;
-import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import
org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.web.SecurityFilterChain;
-import
org.springframework.boot.resttestclient.autoconfigure.AutoConfigureRestTestClient;
-import org.springframework.test.web.servlet.client.RestTestClient;
-import org.springframework.test.web.servlet.client.EntityExchangeResult;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
+import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.http.HttpStatusCode;
+import
org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.web.SecurityFilterChain;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.equalTo;
@EnableAutoConfiguration
@CamelSpringBootTest
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { CamelAutoConfiguration.class,
- SpringBootPlatformHttpRequestTimeoutTest.TestConfiguration.class,
- PlatformHttpComponentAutoConfiguration.class,
SpringBootPlatformHttpAutoConfiguration.class, },
- properties = {"camel.component.platform-http.request-timeout=500"})
-@AutoConfigureMockMvc
-@AutoConfigureRestTestClient
-public class SpringBootPlatformHttpRequestTimeoutTest {
+ SpringBootPlatformHttpHeaderFilterStrategyTest.class,
+ SpringBootPlatformHttpHeaderFilterStrategyTest.TestConfiguration.class,
+ PlatformHttpComponentAutoConfiguration.class,
SpringBootPlatformHttpAutoConfiguration.class })
+public class SpringBootPlatformHttpHeaderFilterStrategyTest {
+
+ @LocalServerPort
+ private Integer port;
- @Autowired
- RestTestClient restTestClient;
+ @BeforeEach
+ void setUp() {
+ RestAssured.port = port;
+ }
@Test
- public void testGetAsync() throws Exception {
- EntityExchangeResult<String> result =
restTestClient.get().uri("/slow-get")
- .exchange()
- .expectBody(String.class)
- .returnResult();
-
Assertions.assertThat(result.getStatus()).isEqualTo(HttpStatusCode.valueOf(503));
+ void customHeaderFilterStrategy() {
+ given()
+ .queryParam("k1", "v1")
+ .queryParam("k2", "v2")
+ .get("/header-filter-strategy")
+ .then()
+ .statusCode(200)
+ .body(equalTo("k1=\nk2=v2"));
}
@Configuration
public static class TestConfiguration {
+
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http)
throws Exception {
http.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
@@ -65,19 +71,26 @@ public class SpringBootPlatformHttpRequestTimeoutTest {
return http.build();
}
+ @Bean("TestHeaderFilterStrategy")
+ public HttpHeaderFilterStrategy testHeaderFilterStrategy() {
+ return new HttpHeaderFilterStrategy() {
+ @Override
+ protected void initialize() {
+ super.initialize();
+ getInFilter().add("k1");
+ }
+ };
+ }
@Bean
- public RouteBuilder platformHttpRouteBuilder() {
+ public RouteBuilder routeBuilder() {
return new RouteBuilder() {
@Override
public void configure() {
- from("platform-http:/slow-get").id("slow-route")
- .process(exchange -> Thread.sleep(1000))
- .setBody().constant("get");
+
from("platform-http:/header-filter-strategy?httpMethodRestrict=GET&headerFilterStrategy=#TestHeaderFilterStrategy")
+
.setBody(simple("k1=${header.k1}\nk2=${header.k2}"));
}
};
}
}
-
-
}
diff --git
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpRequestTimeoutTest.java
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpRequestTimeoutTest.java
index 789f85c8352..32166810821 100644
---
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpRequestTimeoutTest.java
+++
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpRequestTimeoutTest.java
@@ -39,7 +39,7 @@ import org.springframework.http.HttpStatusCode;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { CamelAutoConfiguration.class,
SpringBootPlatformHttpRequestTimeoutTest.TestConfiguration.class,
PlatformHttpComponentAutoConfiguration.class,
SpringBootPlatformHttpAutoConfiguration.class, },
- properties = {"camel.component.platform-http.request-timeout=500"})
+ properties = {"camel.component.platform-http.request-timeout=100"})
@AutoConfigureMockMvc
@AutoConfigureRestTestClient
public class SpringBootPlatformHttpRequestTimeoutTest {
diff --git
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpResponseCodeTest.java
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpResponseCodeTest.java
new file mode 100644
index 00000000000..21a5ca9db6a
--- /dev/null
+++
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpResponseCodeTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.springboot;
+
+import io.restassured.RestAssured;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit6.CamelSpringBootTest;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import
org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.web.SecurityFilterChain;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.equalTo;
+
+@EnableAutoConfiguration
+@CamelSpringBootTest
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { CamelAutoConfiguration.class,
+ SpringBootPlatformHttpResponseCodeTest.class,
+ SpringBootPlatformHttpResponseCodeTest.TestConfiguration.class,
+ PlatformHttpComponentAutoConfiguration.class,
SpringBootPlatformHttpAutoConfiguration.class })
+public class SpringBootPlatformHttpResponseCodeTest {
+
+ @LocalServerPort
+ private Integer port;
+
+ @BeforeEach
+ void setUp() {
+ RestAssured.port = port;
+ }
+
+ @Test
+ void responseCodeViaHeader() {
+ given()
+ .get("/response-code-299")
+ .then()
+ .statusCode(299);
+ }
+
+ @Test
+ void code204Null() {
+ given()
+ .get("/null-body")
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ void code204EmptyString() {
+ given()
+ .get("/empty-string-body")
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ void code204SomeString() {
+ given()
+ .get("/some-string")
+ .then()
+ .statusCode(200)
+ .body(equalTo("No Content"));
+ }
+
+ @Test
+ void code200EmptyString() {
+ given()
+ .get("/empty-string-200")
+ .then()
+ .statusCode(200)
+ .body(equalTo(""));
+ }
+
+ @Configuration
+ public static class TestConfiguration {
+
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity http)
throws Exception {
+ http.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
+ .csrf(csrf -> csrf.disable());
+ return http.build();
+ }
+
+ @Bean
+ public RouteBuilder routeBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+
from("platform-http:/response-code-299?httpMethodRestrict=GET")
+
.setHeader(Exchange.HTTP_RESPONSE_CODE).constant(299);
+
+ from("platform-http:/null-body")
+ .setBody().constant(null);
+
+ from("platform-http:/empty-string-body")
+ .setBody().constant("");
+
+ from("platform-http:/some-string")
+ .setBody().constant("No Content");
+
+ from("platform-http:/empty-string-200")
+ .setHeader(Exchange.HTTP_RESPONSE_CODE,
constant(200))
+ .setBody().constant("");
+ }
+ };
+ }
+ }
+}
diff --git
a/components-starter/camel-platform-http-starter/src/test/resources/org/apache/camel/component/platform/http/springboot/example.pdf
b/components-starter/camel-platform-http-starter/src/test/resources/org/apache/camel/component/platform/http/springboot/example.pdf
new file mode 100644
index 00000000000..2ed6fe99a57
Binary files /dev/null and
b/components-starter/camel-platform-http-starter/src/test/resources/org/apache/camel/component/platform/http/springboot/example.pdf
differ