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

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


The following commit(s) were added to refs/heads/camel-4.10.x by this push:
     new 943f09b8c39 CAMEL-22116: Fix camel-openapi-validator to better support 
base-path such as SB war apps that are seperated by context-path
943f09b8c39 is described below

commit 943f09b8c3967cb86ed1bc3bcb4f1ab672058fdb
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Jun 3 15:15:57 2025 +0200

    CAMEL-22116: Fix camel-openapi-validator to better support base-path such 
as SB war apps that are seperated by context-path
---
 .../client/OpenApiRestClientRequestValidator.java  |  5 ++-
 .../DefaultRestOpenapiProcessorStrategy.java       |  5 +--
 .../camel/component/rest/openapi/OpenApiUtils.java |  6 ++--
 .../rest/openapi/RestOpenApiEndpoint.java          |  1 +
 .../component/rest/openapi/RestOpenApiHelper.java  | 39 ++++++++++++++++++++++
 .../rest/openapi/RestOpenApiProcessor.java         |  2 +-
 .../rest/openapi/RestOpenapiProcessorStrategy.java |  8 +++--
 .../openapi/RestOpenapiProcessorStrategyTest.java  |  2 +-
 8 files changed, 57 insertions(+), 11 deletions(-)

diff --git 
a/components/camel-openapi-validator/src/main/java/org/apache/camel/component/rest/openapi/validator/client/OpenApiRestClientRequestValidator.java
 
b/components/camel-openapi-validator/src/main/java/org/apache/camel/component/rest/openapi/validator/client/OpenApiRestClientRequestValidator.java
index 9a97f9838cc..b6e857fc268 100644
--- 
a/components/camel-openapi-validator/src/main/java/org/apache/camel/component/rest/openapi/validator/client/OpenApiRestClientRequestValidator.java
+++ 
b/components/camel-openapi-validator/src/main/java/org/apache/camel/component/rest/openapi/validator/client/OpenApiRestClientRequestValidator.java
@@ -23,6 +23,7 @@ import 
com.atlassian.oai.validator.report.SimpleValidationReportFormat;
 import com.atlassian.oai.validator.report.ValidationReport;
 import io.swagger.v3.oas.models.OpenAPI;
 import org.apache.camel.Exchange;
+import org.apache.camel.component.rest.openapi.RestOpenApiComponent;
 import org.apache.camel.component.rest.openapi.RestOpenApiHelper;
 import org.apache.camel.http.base.HttpHeaderFilterStrategy;
 import org.apache.camel.spi.RestClientRequestValidator;
@@ -55,8 +56,10 @@ public class OpenApiRestClientRequestValidator implements 
RestClientRequestValid
         String method = exchange.getMessage().getHeader(Exchange.HTTP_METHOD, 
String.class);
         String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH, 
String.class);
 
+        // find the base-path which can be configured in various places
+        RestOpenApiComponent comp = (RestOpenApiComponent) 
exchange.getContext().hasComponent("rest-openapi");
+        String basePath = 
RestOpenApiHelper.determineBasePath(exchange.getContext(), comp, null, openAPI);
         // need to clip base-path
-        String basePath = RestOpenApiHelper.getBasePathFromOpenApi(openAPI);
         if (path != null && path.startsWith(basePath)) {
             path = path.substring(basePath.length());
         }
diff --git 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
index c931dc20102..b107edc8de6 100644
--- 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
+++ 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/DefaultRestOpenapiProcessorStrategy.java
@@ -75,7 +75,8 @@ public class DefaultRestOpenapiProcessorStrategy extends 
ServiceSupport
     private final List<String> uris = new ArrayList<>();
 
     @Override
-    public void validateOpenApi(OpenAPI openAPI, PlatformHttpConsumerAware 
platformHttpConsumer) throws Exception {
+    public void validateOpenApi(OpenAPI openAPI, String basePath, 
PlatformHttpConsumerAware platformHttpConsumer)
+            throws Exception {
         List<String> ids = new ArrayList<>();
         for (var e : openAPI.getPaths().entrySet()) {
             for (var o : e.getValue().readOperationsMap().entrySet()) {
@@ -115,7 +116,7 @@ public class DefaultRestOpenapiProcessorStrategy extends 
ServiceSupport
         // enlist open-api rest services
         PlatformHttpComponent phc = camelContext.getComponent("platform-http", 
PlatformHttpComponent.class);
         if (phc != null) {
-            String path = RestOpenApiHelper.getBasePathFromOpenApi(openAPI);
+            String path = basePath;
             if (path == null || path.isEmpty() || path.equals("/")) {
                 path = "";
             }
diff --git 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/OpenApiUtils.java
 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/OpenApiUtils.java
index ff7bd82268d..4a5ed22ceae 100644
--- 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/OpenApiUtils.java
+++ 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/OpenApiUtils.java
@@ -64,9 +64,9 @@ public class OpenApiUtils {
 
     private final AtomicBoolean packageScanInit = new AtomicBoolean();
     private final Set<Class<?>> scannedClasses = new HashSet<>();
-    private CamelContext camelContext;
-    private String bindingPackage;
-    private Components components;
+    private final CamelContext camelContext;
+    private final String bindingPackage;
+    private final Components components;
 
     public OpenApiUtils(CamelContext camelContext, String bindingPackage, 
Components components) {
         this.camelContext = camelContext;
diff --git 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
index 3874bd3bcc4..0684844c045 100644
--- 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
+++ 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java
@@ -507,6 +507,7 @@ public final class RestOpenApiEndpoint extends 
DefaultEndpoint {
         return new RestOpenApiProducer(endpoint.createProducer(), hasHost, 
requestValidator);
     }
 
+    @Deprecated
     String determineBasePath(final OpenAPI openapi) {
         if (isNotEmpty(basePath)) {
             return basePath;
diff --git 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiHelper.java
 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiHelper.java
index 26114dcc3b3..709c829a548 100644
--- 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiHelper.java
+++ 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiHelper.java
@@ -27,11 +27,15 @@ import java.util.stream.Stream;
 
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.servers.Server;
+import org.apache.camel.CamelContext;
 import org.apache.camel.spi.ContentTypeAware;
 import org.apache.camel.spi.Resource;
+import org.apache.camel.spi.RestConfiguration;
+import org.apache.camel.support.CamelContextHelper;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.StringHelper;
 
+import static org.apache.camel.util.ObjectHelper.isNotEmpty;
 import static org.apache.camel.util.StringHelper.notEmpty;
 
 public final class RestOpenApiHelper {
@@ -94,6 +98,41 @@ public final class RestOpenApiHelper {
         return location.toLowerCase().endsWith(".yml") || 
location.toLowerCase().endsWith(".yaml");
     }
 
+    /**
+     * Determines the base-path according to various configuration on 
component/endpoint and in the spec
+     */
+    public static String determineBasePath(
+            CamelContext camelContext, RestOpenApiComponent component, 
RestOpenApiEndpoint endpoint, OpenAPI openAPI) {
+        if (endpoint != null && isNotEmpty(endpoint.getBasePath())) {
+            return endpoint.getBasePath();
+        }
+
+        if (component != null) {
+            String componentBasePath = component.getBasePath();
+            if (isNotEmpty(componentBasePath)) {
+                return componentBasePath;
+            }
+        }
+
+        if (openAPI != null) {
+            String specificationBasePath = 
RestOpenApiHelper.getBasePathFromOpenApi(openAPI);
+            if (isNotEmpty(specificationBasePath)) {
+                return specificationBasePath;
+            }
+        }
+
+        String cn = endpoint != null ? endpoint.determineComponentName() : 
null;
+        RestConfiguration restConfiguration
+                = CamelContextHelper.getRestConfiguration(camelContext, null, 
cn);
+        String restConfigurationBasePath = restConfiguration.getContextPath();
+
+        if (isNotEmpty(restConfigurationBasePath)) {
+            return restConfigurationBasePath;
+        }
+
+        return RestOpenApiComponent.DEFAULT_BASE_PATH;
+    }
+
     public static String getBasePathFromOpenApi(final OpenAPI openApi) {
         String basePath = null;
         if (openApi.getServers() != null) {
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 b8b2c02380b..626372536f7 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
@@ -188,7 +188,7 @@ public class RestOpenApiProcessor extends 
DelegateAsyncProcessor implements Came
         ServiceHelper.initService(restOpenapiProcessorStrategy);
 
         // validate openapi contract
-        restOpenapiProcessorStrategy.validateOpenApi(openAPI, 
platformHttpConsumer);
+        restOpenapiProcessorStrategy.validateOpenApi(openAPI, basePath, 
platformHttpConsumer);
     }
 
     private RestBindingConfiguration createRestBindingConfiguration(Operation 
o) throws Exception {
diff --git 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
index 7c639071633..ccf1ca11f32 100644
--- 
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
+++ 
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategy.java
@@ -56,10 +56,12 @@ public interface RestOpenapiProcessorStrategy {
      * Validates the OpenAPI specification on startup
      *
      * @param  openAPI              the openapi specification
+     * @param  basePath             the base path
      * @param  platformHttpConsumer the platform http consumer
      * @throws Exception            is thrown if validation error on startup
      */
-    default void validateOpenApi(OpenAPI openAPI, PlatformHttpConsumerAware 
platformHttpConsumer) throws Exception {
+    default void validateOpenApi(OpenAPI openAPI, String basePath, 
PlatformHttpConsumerAware platformHttpConsumer)
+            throws Exception {
         // noop
     }
 
@@ -75,7 +77,7 @@ public interface RestOpenapiProcessorStrategy {
      * @param  callback  the AsyncCallback will be invoked when the processing 
of the exchange is completed. If the
      *                   exchange is completed synchronously, then the 
callback is also invoked synchronously. The
      *                   callback should therefore be careful of starting 
recursive loop.
-     * @return           (doneSync) true to continue execute synchronously, 
false to continue being executed
+     * @return           (doneSync) true to continue to execute synchronously, 
false to continue being executed
      *                   asynchronously
      */
     boolean process(
@@ -91,7 +93,7 @@ public interface RestOpenapiProcessorStrategy {
      * @param  callback the AsyncCallback will be invoked when the processing 
of the exchange is completed. If the
      *                  exchange is completed synchronously, then the callback 
is also invoked synchronously. The
      *                  callback should therefore be careful of starting 
recursive loop.
-     * @return          (doneSync) true to continue execute synchronously, 
false to continue being executed
+     * @return          (doneSync) true to continue to execute synchronously, 
false to continue being executed
      *                  asynchronously
      */
     boolean processApiSpecification(String specificationUri, Exchange 
exchange, AsyncCallback callback);
diff --git 
a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategyTest.java
 
b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategyTest.java
index 7c906b41106..567c4835262 100644
--- 
a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategyTest.java
+++ 
b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/RestOpenapiProcessorStrategyTest.java
@@ -44,7 +44,7 @@ class RestOpenapiProcessorStrategyTest extends 
ManagedCamelTestSupport {
         ((DefaultRestOpenapiProcessorStrategy) 
restOpenapiProcessorStrategy).setCamelContext(camelContext);
         restOpenapiProcessorStrategy.setMissingOperation("fail");
         Exception ex = assertThrows(IllegalArgumentException.class,
-                () -> 
restOpenapiProcessorStrategy.validateOpenApi(getOpenApi(), 
mock(PlatformHttpConsumerAware.class)));
+                () -> 
restOpenapiProcessorStrategy.validateOpenApi(getOpenApi(), null, 
mock(PlatformHttpConsumerAware.class)));
         assertTrue(ex.getMessage().contains("direct:GENOPID_GET.users"));
         assertTrue(ex.getMessage().contains("direct:GENOPID_GET.user._id_"));
 

Reply via email to