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 2024/03/28 14:40:26 UTC

(camel) 12/38: CAMEL-20557: Rest DSL to use openapi spec directly

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch openapi2
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f3434923f8f8f293eb2a72841d638a21812ca861
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Mar 25 10:27:09 2024 +0100

    CAMEL-20557: Rest DSL to use openapi spec directly
---
 .../vertx/PlatformHttpRestOpenApiConsumerTest.java | 56 ++++++++++++++++++++++
 .../rest/openapi/RestOpenApiProcessor.java         | 35 ++++++--------
 2 files changed, 71 insertions(+), 20 deletions(-)

diff --git a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
index ab01d018caa..6c9865ecb59 100644
--- a/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
+++ b/components/camel-platform-http-vertx/src/test/java/org/apache/camel/component/platform/http/vertx/PlatformHttpRestOpenApiConsumerTest.java
@@ -54,4 +54,60 @@ public class PlatformHttpRestOpenApiConsumerTest {
         }
     }
 
+    @Test
+    public void testRestOpenApiNotFound() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("rest-openapi:classpath:openapi-v3.json")
+                            .log("dummy");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .get("/api/v3/pet/123/unknown")
+                    .then()
+                    .statusCode(404);
+        } finally {
+            context.stop();
+        }
+    }
+
+    @Test
+    public void testRestOpenApiNotAllowed() throws Exception {
+        final CamelContext context = VertxPlatformHttpEngineTest.createCamelContext();
+
+        try {
+            context.addRoutes(new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("rest-openapi:classpath:openapi-v3.json")
+                            .log("dummy");
+
+                    from("direct:getPetById")
+                            .setBody().constant("{\"pet\": \"tony the tiger\"}");
+                }
+            });
+
+            context.start();
+
+            given()
+                    .when()
+                    .put("/api/v3/pet/123")
+                    .then()
+                    .statusCode(405);
+        } finally {
+            context.stop();
+        }
+    }
+
 }
diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
index 283327a3c6a..f0c8bb351a7 100644
--- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
+++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiProcessor.java
@@ -17,12 +17,11 @@
 package org.apache.camel.component.rest.openapi;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
-import java.util.concurrent.RejectedExecutionException;
 
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
-import io.swagger.v3.oas.models.PathItem;
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
@@ -34,6 +33,9 @@ import org.apache.camel.support.service.ServiceHelper;
 
 public class RestOpenApiProcessor extends DelegateAsyncProcessor implements CamelContextAware {
 
+    private static final List<String> METHODS
+            = Arrays.asList("GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "OPTIONS", "CONNECT", "PATCH");
+
     private CamelContext camelContext;
     private final OpenAPI openAPI;
     private final String basePath;
@@ -68,9 +70,7 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
         // TODO: check if valid operation according to OpenApi
-        // TODO: validate GET/POST etc
         // TODO: RequestValidator
-        // TODO: 404 and so on
         // TODO: binding
 
         String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH, String.class);
@@ -86,26 +86,21 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
             return restOpenapiProcessorStrategy.process(o, path, exchange, callback);
         }
 
-        // no operation found so it's a 404
-        exchange.setException(new RejectedExecutionException());
-        exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 404);
+        // okay we cannot process this requires so return either 404 or 405.
+        // to know if its 405 then we need to check if any other HTTP method would have a consumer for the "same" request
+        final String contextPath = path;
+        boolean hasAnyMethod
+                = METHODS.stream().anyMatch(v -> RestConsumerContextPathMatcher.matchBestPath(v, contextPath, paths) != null);
+        if (hasAnyMethod) {
+            exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 405);
+        } else {
+            exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 404);
+        }
+        exchange.setRouteStop(true);
         callback.done(true);
         return true;
     }
 
-    protected Operation asOperation(PathItem item, String verb) {
-        return switch (verb) {
-            case "GET" -> item.getGet();
-            case "DELETE" -> item.getDelete();
-            case "HEAD" -> item.getHead();
-            case "PATCH" -> item.getPatch();
-            case "OPTIONS" -> item.getOptions();
-            case "PUT" -> item.getPut();
-            case "POST" -> item.getPost();
-            default -> null;
-        };
-    }
-
     @Override
     protected void doBuild() throws Exception {
         super.doBuild();