You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ja...@apache.org on 2021/04/30 07:55:05 UTC

[camel] branch main updated: CAMEL-16560: Consider empty string in clientRequestValidation for REST HTTP body

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 d85173a  CAMEL-16560: Consider empty string in clientRequestValidation for REST HTTP body
d85173a is described below

commit d85173a64c482fee9a76bb48747d98013d208ccf
Author: James Netherton <ja...@gmail.com>
AuthorDate: Fri Apr 30 08:22:46 2021 +0100

    CAMEL-16560: Consider empty string in clientRequestValidation for REST HTTP body
---
 .../jetty/rest/RestJettyRequiredBodyTest.java      |  17 +-
 .../http/vertx/VertxPlatformHttpConsumer.java      |   6 +-
 .../http/vertx/VertxPlatformHttpEngineTest.java    | 192 +++++++++++++--------
 .../apache/camel/processor/RestBindingAdvice.java  |   4 +-
 4 files changed, 144 insertions(+), 75 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 0d1cee8..b591537 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
@@ -41,7 +41,7 @@ public class RestJettyRequiredBodyTest extends BaseJettyTest {
     }
 
     @Test
-    public void testJettyInvalid() {
+    public void testJettyInvalidNullBody() {
         fluentTemplate = fluentTemplate.withHeader(Exchange.CONTENT_TYPE, "application/json")
                 .withHeader("Accept", "application/json")
                 .withHeader(Exchange.HTTP_METHOD, "post")
@@ -54,6 +54,21 @@ public class RestJettyRequiredBodyTest extends BaseJettyTest {
         assertEquals("The request body is missing.", cause.getResponseBody());
     }
 
+    @Test
+    public void testJettyInvalidEmptyBody() {
+        fluentTemplate = fluentTemplate.withHeader(Exchange.CONTENT_TYPE, "application/json")
+                .withHeader("Accept", "application/json")
+                .withHeader(Exchange.HTTP_METHOD, "post")
+                .withBody(" ")
+                .to("http://localhost:" + getPort() + "/users/123/update");
+
+        Exception ex = assertThrows(CamelExecutionException.class, () -> fluentTemplate.request(String.class));
+
+        HttpOperationFailedException cause = assertIsInstanceOf(HttpOperationFailedException.class, ex.getCause());
+        assertEquals(400, cause.getStatusCode());
+        assertEquals("The request body is missing.", cause.getResponseBody());
+    }
+
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
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 e2264e7..d1f1471 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
@@ -247,7 +247,11 @@ public class VertxPlatformHttpConsumer extends DefaultConsumer {
                     }
                 }
             }
-            result.setBody(body);
+
+            if (!body.isEmpty()) {
+                result.setBody(body);
+            }
+
             if (isMultipartFormData) {
                 populateAttachments(ctx.fileUploads(), result);
             }
diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngineTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngineTest.java
index 1cfc2a3..3d0b2d2 100644
--- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngineTest.java
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpEngineTest.java
@@ -24,13 +24,14 @@ import java.util.concurrent.TimeUnit;
 
 import javax.activation.DataHandler;
 
+import io.restassured.RestAssured;
 import io.vertx.core.VertxOptions;
-import io.vertx.ext.web.handler.BodyHandler;
 import org.apache.camel.CamelContext;
 import org.apache.camel.attachment.AttachmentMessage;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.platform.http.PlatformHttpComponent;
 import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.model.rest.RestParamType;
 import org.apache.camel.support.jsse.KeyManagersParameters;
 import org.apache.camel.support.jsse.KeyStoreParameters;
 import org.apache.camel.support.jsse.SSLContextParameters;
@@ -87,14 +88,8 @@ public class VertxPlatformHttpEngineTest {
 
     @Test
     public void testEngineSetup() throws Exception {
-        final int port = AvailablePortFinder.getNextAvailable();
-        final CamelContext context = new DefaultCamelContext();
-
+        final CamelContext context = createCamelContext();
         try {
-            VertxPlatformHttpServerConfiguration conf = new VertxPlatformHttpServerConfiguration();
-            conf.setBindPort(port);
-
-            context.addService(new VertxPlatformHttpServer(conf));
             context.start();
 
             assertThat(VertxPlatformHttpRouter.lookup(context)).isNotNull();
@@ -109,14 +104,9 @@ public class VertxPlatformHttpEngineTest {
 
     @Test
     public void testEngine() throws Exception {
-        final int port = AvailablePortFinder.getNextAvailable();
-        final CamelContext context = new DefaultCamelContext();
+        final CamelContext context = createCamelContext();
 
         try {
-            VertxPlatformHttpServerConfiguration conf = new VertxPlatformHttpServerConfiguration();
-            conf.setBindPort(port);
-
-            context.addService(new VertxPlatformHttpServer(conf));
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() throws Exception {
@@ -132,7 +122,6 @@ public class VertxPlatformHttpEngineTest {
             context.start();
 
             given()
-                    .port(conf.getBindPort())
                     .when()
                     .get("/get")
                     .then()
@@ -140,7 +129,6 @@ public class VertxPlatformHttpEngineTest {
                     .body(equalTo("get"));
 
             given()
-                    .port(conf.getBindPort())
                     .body("post")
                     .when()
                     .post("/post")
@@ -155,20 +143,15 @@ public class VertxPlatformHttpEngineTest {
 
     @Test
     public void testSlowConsumer() throws Exception {
-        final int port = AvailablePortFinder.getNextAvailable();
-        final CamelContext context = new DefaultCamelContext();
+        final CamelContext context = createCamelContext();
 
         try {
-            VertxPlatformHttpServerConfiguration conf = new VertxPlatformHttpServerConfiguration();
-            conf.setBindPort(port);
-
             context.getRegistry().bind(
                     "vertx-options",
                     new VertxOptions()
                             .setMaxEventLoopExecuteTime(2)
                             .setMaxEventLoopExecuteTimeUnit(TimeUnit.SECONDS));
 
-            context.addService(new VertxPlatformHttpServer(conf));
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() throws Exception {
@@ -182,7 +165,6 @@ public class VertxPlatformHttpEngineTest {
             context.start();
 
             given()
-                    .port(conf.getBindPort())
                     .when()
                     .get("/get")
                     .then()
@@ -196,14 +178,9 @@ public class VertxPlatformHttpEngineTest {
 
     @Test
     public void testFailingConsumer() throws Exception {
-        final int port = AvailablePortFinder.getNextAvailable();
-        final CamelContext context = new DefaultCamelContext();
+        final CamelContext context = createCamelContext();
 
         try {
-            VertxPlatformHttpServerConfiguration conf = new VertxPlatformHttpServerConfiguration();
-            conf.setBindPort(port);
-
-            context.addService(new VertxPlatformHttpServer(conf));
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() throws Exception {
@@ -218,7 +195,6 @@ public class VertxPlatformHttpEngineTest {
             context.start();
 
             given()
-                    .port(conf.getBindPort())
                     .when()
                     .get("/get")
                     .then()
@@ -231,16 +207,11 @@ public class VertxPlatformHttpEngineTest {
 
     @Test
     public void testEngineSSL() throws Exception {
-        VertxPlatformHttpServerConfiguration conf = new VertxPlatformHttpServerConfiguration();
-        conf.setSslContextParameters(serverSSLParameters);
-        conf.setBindPort(AvailablePortFinder.getNextAvailable());
-
-        CamelContext context = new DefaultCamelContext();
+        final CamelContext context
+                = createCamelContext(configuration -> configuration.setSslContextParameters(serverSSLParameters));
 
         try {
-            context.addService(new VertxPlatformHttpServer(conf));
             context.getRegistry().bind("clientSSLContextParameters", clientSSLParameters);
-
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() throws Exception {
@@ -252,7 +223,7 @@ public class VertxPlatformHttpEngineTest {
             context.start();
 
             String result = context.createFluentProducerTemplate()
-                    .toF("https://localhost:%d?sslContextParameters=#clientSSLContextParameters", conf.getBindPort())
+                    .toF("https://localhost:%d?sslContextParameters=#clientSSLContextParameters", RestAssured.port)
                     .withBody("test")
                     .request(String.class);
 
@@ -264,15 +235,10 @@ public class VertxPlatformHttpEngineTest {
 
     @Test
     public void testEngineGlobalSSL() throws Exception {
-        VertxPlatformHttpServerConfiguration conf = new VertxPlatformHttpServerConfiguration();
-        conf.setUseGlobalSslContextParameters(true);
-        conf.setBindPort(AvailablePortFinder.getNextAvailable());
-
-        CamelContext context = new DefaultCamelContext();
+        final CamelContext context = createCamelContext(configuration -> configuration.setUseGlobalSslContextParameters(true));
 
         try {
             context.setSSLContextParameters(serverSSLParameters);
-            context.addService(new VertxPlatformHttpServer(conf));
             context.getRegistry().bind("clientSSLContextParameters", clientSSLParameters);
 
             context.addRoutes(new RouteBuilder() {
@@ -286,7 +252,7 @@ public class VertxPlatformHttpEngineTest {
             context.start();
 
             String result = context.createFluentProducerTemplate()
-                    .toF("https://localhost:%d?sslContextParameters=#clientSSLContextParameters", conf.getBindPort())
+                    .toF("https://localhost:%d?sslContextParameters=#clientSSLContextParameters", RestAssured.port)
                     .withBody("test")
                     .request(String.class);
 
@@ -298,15 +264,12 @@ public class VertxPlatformHttpEngineTest {
 
     @Test
     public void testEngineCORS() throws Exception {
-        VertxPlatformHttpServerConfiguration conf = new VertxPlatformHttpServerConfiguration();
-        conf.setBindPort(AvailablePortFinder.getNextAvailable());
-        conf.getCors().setEnabled(true);
-        conf.getCors().setMethods(Arrays.asList("GET", "POST"));
-
-        CamelContext context = new DefaultCamelContext();
+        final CamelContext context = createCamelContext(configuration -> {
+            configuration.getCors().setEnabled(true);
+            configuration.getCors().setMethods(Arrays.asList("GET", "POST"));
+        });
 
         try {
-            context.addService(new VertxPlatformHttpServer(conf));
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() throws Exception {
@@ -322,7 +285,6 @@ public class VertxPlatformHttpEngineTest {
             final String headers = "X-Custom";
 
             given()
-                    .port(conf.getBindPort())
                     .header("Origin", origin)
                     .header("Access-Control-Request-Method", methods)
                     .header("Access-Control-Request-Headers", headers)
@@ -340,13 +302,9 @@ public class VertxPlatformHttpEngineTest {
 
     @Test
     public void testMatchOnUriPrefix() throws Exception {
-        VertxPlatformHttpServerConfiguration conf = new VertxPlatformHttpServerConfiguration();
-        conf.setBindPort(AvailablePortFinder.getNextAvailable());
-
-        CamelContext context = new DefaultCamelContext();
+        final CamelContext context = createCamelContext();
         try {
             final String greeting = "Hello Camel";
-            context.addService(new VertxPlatformHttpServer(conf));
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() throws Exception {
@@ -358,14 +316,12 @@ public class VertxPlatformHttpEngineTest {
             context.start();
 
             given()
-                    .port(conf.getBindPort())
                     .when()
                     .get("/greeting")
                     .then()
                     .statusCode(404);
 
             given()
-                    .port(conf.getBindPort())
                     .when()
                     .get("/greeting/Camel")
                     .then()
@@ -373,7 +329,6 @@ public class VertxPlatformHttpEngineTest {
                     .body(equalTo(greeting));
 
             given()
-                    .port(conf.getBindPort())
                     .when()
                     .get("/greeting/Camel/other/path/")
                     .then()
@@ -386,23 +341,18 @@ public class VertxPlatformHttpEngineTest {
 
     @Test
     public void testFileUpload() throws Exception {
-        final int port = AvailablePortFinder.getNextAvailable();
         final String fileContent = "Test multipart upload content";
         final File tempFile = File.createTempFile("platform-http", ".txt");
-        final CamelContext context = new DefaultCamelContext();
-
-        try {
-            VertxPlatformHttpServerConfiguration conf = new VertxPlatformHttpServerConfiguration();
-            conf.setBindPort(port);
-
+        final CamelContext context = createCamelContext(configuration -> {
             VertxPlatformHttpServerConfiguration.BodyHandler bodyHandler
                     = new VertxPlatformHttpServerConfiguration.BodyHandler();
             bodyHandler.setUploadsDirectory(tempFile.getParent());
-            conf.setBodyHandler(bodyHandler);
+            configuration.setBodyHandler(bodyHandler);
+        });
 
+        try {
             Files.write(tempFile.toPath(), fileContent.getBytes(StandardCharsets.UTF_8));
 
-            context.addService(new VertxPlatformHttpServer(conf));
             context.addRoutes(new RouteBuilder() {
                 @Override
                 public void configure() throws Exception {
@@ -418,7 +368,6 @@ public class VertxPlatformHttpEngineTest {
             context.start();
 
             given()
-                    .port(conf.getBindPort())
                     .multiPart(tempFile)
                     .when()
                     .post("/upload")
@@ -429,4 +378,105 @@ public class VertxPlatformHttpEngineTest {
             context.stop();
         }
     }
+
+    @Test
+    public void testFormPost() throws Exception {
+        final CamelContext context = createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("platform-http:/form/post")
+                            .convertBodyTo(String.class);
+                }
+            });
+
+            context.start();
+
+            given()
+                    .formParam("foo", "bar")
+                    .formParam("cheese", "wine")
+                    .when()
+                    .post("/form/post")
+                    .then()
+                    .statusCode(200)
+                    .body(is("{foo=bar, cheese=wine}"));
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testBodyClientRequestValidation() throws Exception {
+        final CamelContext context = createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    restConfiguration().component("platform-http");
+
+                    rest("/rest")
+                            .post("/validate/body")
+                            .clientRequestValidation(true)
+                            .param().name("body").type(RestParamType.body).required(true).endParam()
+                            .route()
+                            .setBody(simple("Hello ${body}"))
+                            .endRest();
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .post("/rest/validate/body")
+                    .then()
+                    .statusCode(400)
+                    .body(is("The request body is missing."));
+
+            given()
+                    .body(" ")
+                    .when()
+                    .post("/rest/validate/body")
+                    .then()
+                    .statusCode(400)
+                    .body(is("The request body is missing."));
+
+            given()
+                    .body("Camel Platform HTTP Vert.x")
+                    .when()
+                    .post("/rest/validate/body")
+                    .then()
+                    .statusCode(200)
+                    .body(is("Hello Camel Platform HTTP Vert.x"));
+        } finally {
+            context.stop();
+        }
+    }
+
+    private CamelContext createCamelContext() throws Exception {
+        return createCamelContext(null);
+    }
+
+    private CamelContext createCamelContext(ServerConfigurationCustomizer customizer) throws Exception {
+        int port = AvailablePortFinder.getNextAvailable();
+        VertxPlatformHttpServerConfiguration conf = new VertxPlatformHttpServerConfiguration();
+        conf.setBindPort(port);
+
+        RestAssured.port = port;
+
+        if (customizer != null) {
+            customizer.customize(conf);
+        }
+
+        CamelContext context = new DefaultCamelContext();
+        context.addService(new VertxPlatformHttpServer(conf));
+        return context;
+    }
+
+    interface ServerConfigurationCustomizer {
+        void customize(VertxPlatformHttpServerConfiguration configuration);
+    }
 }
diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/RestBindingAdvice.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/RestBindingAdvice.java
index af98fff..db113be 100644
--- a/core/camel-core-processor/src/main/java/org/apache/camel/processor/RestBindingAdvice.java
+++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/RestBindingAdvice.java
@@ -268,11 +268,11 @@ public class RestBindingAdvice implements CamelInternalProcessorAdvice<Map<Strin
                 // so force reading the body as a String which we can work with
                 if (body == null) {
                     body = MessageHelper.extractBodyAsString(exchange.getIn());
-                    if (body != null) {
+                    if (ObjectHelper.isNotEmpty(body)) {
                         exchange.getIn().setBody(body);
                     }
                 }
-                if (body == null) {
+                if (ObjectHelper.isEmpty(body)) {
                     // this is a bad request, the client did not include a message body
                     exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
                     exchange.getMessage().setBody("The request body is missing.");