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/06/10 07:20:27 UTC
(camel) 02/03: CAMEL-20832: camel-openapi-validator to use Atlassian openapi validator for rest-dsl
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch vc4
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 14f1b58af44e8a97fea86aa668129eed8ee143b5
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Jun 6 07:06:09 2024 +0200
CAMEL-20832: camel-openapi-validator to use Atlassian openapi validator for rest-dsl
---
.../camel/catalog/components/rest-openapi.json | 2 +-
.../client/OpenApiRestClientRequestValidator.java | 41 +++++++++++++++++++++-
.../camel/component/rest/openapi/rest-openapi.json | 2 +-
.../DefaultRestOpenapiProcessorStrategy.java | 3 +-
.../rest/openapi/RestOpenApiEndpoint.java | 1 +
.../rest/openapi/RestOpenApiProcessor.java | 2 +-
.../rest/openapi/RestOpenapiProcessorStrategy.java | 3 +-
.../org/apache/camel/ExchangeConstantProvider.java | 3 +-
.../src/main/java/org/apache/camel/Exchange.java | 1 +
.../camel/support/processor/RestBindingAdvice.java | 2 ++
.../dsl/RestOpenApiEndpointBuilderFactory.java | 8 +++--
.../camel/kotlin/components/RestOpenapiUriDsl.kt | 3 +-
12 files changed, 60 insertions(+), 11 deletions(-)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
index 32f5b67f650..f978b2d54e9 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json
@@ -48,7 +48,7 @@
"operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
"apiContextPath": { "index": 2, "kind": "parameter", "displayName": "Api Context Path", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the context-path to use for servicing the OpenAPI specification" },
"clientRequestValidation": { "index": 3, "kind": "parameter", "displayName": "Client Request Validation", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable validation of the client request to check if the incoming request is valid according to the OpenAPI specification" },
- "consumes": { "index": 4, "kind": "parameter", "displayName": "Consumes", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
+ "consumes": { "index": 4, "kind": "parameter", "displayName": "Consumes", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates or multiple types as applicat [...]
"missingOperation": { "index": 5, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
"bridgeErrorHandler": { "index": 6, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming [...]
"consumerComponentName": { "index": 7, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
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 7c8c37fff76..989478c01e0 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
@@ -16,15 +16,54 @@
*/
package org.apache.camel.component.rest.openapi.validator.client;
+import com.atlassian.oai.validator.OpenApiInteractionValidator;
+import com.atlassian.oai.validator.model.SimpleRequest;
+import com.atlassian.oai.validator.report.ValidationReport;
+import io.swagger.v3.oas.models.OpenAPI;
import org.apache.camel.Exchange;
import org.apache.camel.spi.RestClientRequestValidator;
import org.apache.camel.spi.annotations.JdkService;
+import org.apache.camel.support.ExchangeHelper;
+import org.apache.camel.support.MessageHelper;
@JdkService(RestClientRequestValidator.FACTORY)
-public class OpenApiRestClientRequestValidator implements RestClientRequestValidator{
+public class OpenApiRestClientRequestValidator implements RestClientRequestValidator {
+
+ // TODO: use default validator if no OpenAPI
@Override
public ValidationError validate(Exchange exchange, ValidationContext validationContent) {
+ OpenAPI openAPI = exchange.getProperty(Exchange.REST_OPENAPI, OpenAPI.class);
+ if (openAPI == null) {
+ return null;
+ }
+
+ String method = exchange.getMessage().getHeader(Exchange.HTTP_METHOD, String.class);
+ String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH, String.class);
+ String accept = exchange.getMessage().getHeader("Accept", String.class);
+ String contentType = ExchangeHelper.getContentType(exchange);
+ String body = MessageHelper.extractBodyAsString(exchange.getIn());
+
+ SimpleRequest.Builder builder = new SimpleRequest.Builder(method, path, false);
+ if (contentType != null) {
+ builder.withContentType(contentType);
+ }
+ if (accept != null) {
+ builder.withAccept(accept);
+ }
+ if (body != null) {
+ builder.withBody(body);
+ }
+
+ Thread.currentThread().setContextClassLoader(exchange.getContext().getApplicationContextClassLoader());
+ OpenApiInteractionValidator validator = OpenApiInteractionValidator.createFor(openAPI).build();
+ ValidationReport report = validator.validateRequest(builder.build());
+ if (report.hasErrors()) {
+ for (var m : report.getMessages()) {
+ System.out.println(m);
+ }
+ }
return null;
}
+
}
diff --git a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
index 32f5b67f650..f978b2d54e9 100644
--- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
+++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json
@@ -48,7 +48,7 @@
"operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" },
"apiContextPath": { "index": 2, "kind": "parameter", "displayName": "Api Context Path", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the context-path to use for servicing the OpenAPI specification" },
"clientRequestValidation": { "index": 3, "kind": "parameter", "displayName": "Client Request Validation", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable validation of the client request to check if the incoming request is valid according to the OpenAPI specification" },
- "consumes": { "index": 4, "kind": "parameter", "displayName": "Consumes", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates to the value of Accept HTTP h [...]
+ "consumes": { "index": 4, "kind": "parameter", "displayName": "Consumes", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "What payload type this component capable of consuming. Could be one type, like application\/json or multiple types as application\/json, application\/xml; q=0.5 according to the RFC7231. This equates or multiple types as applicat [...]
"missingOperation": { "index": 5, "kind": "parameter", "displayName": "Missing Operation", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "fail", "ignore", "mock" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "fail", "description": "Whether the consumer should fail,ignore or return a mock response for OpenAPI operations that are not mapped to a corresponding route." },
"bridgeErrorHandler": { "index": 6, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming [...]
"consumerComponentName": { "index": 7, "kind": "parameter", "displayName": "Consumer Component Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of the Camel component that will service the requests. The component must be present in Camel registry and it must implement RestOpenApiConsumerFactory service provider interfa [...]
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 e0bff0f9672..d023b7b43b8 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
@@ -169,7 +169,7 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
}
@Override
- public boolean process(
+ public boolean process(OpenAPI openAPI,
Operation operation, String verb, String path,
RestBindingAdvice binding,
Exchange exchange, AsyncCallback callback) {
@@ -190,6 +190,7 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport
// there is a route so process
Map<String, Object> state;
try {
+ exchange.setProperty(Exchange.REST_OPENAPI, openAPI);
state = binding.before(exchange);
} catch (Exception e) {
exchange.setException(e);
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 dee36ced6a1..f7780434237 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
@@ -128,6 +128,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint {
label = "producer")
private String operationId;
@UriParam(description = "What payload type this component capable of consuming. Could be one type, like `application/json`"
+ + " or multiple types as `application/json, application/xml; q=0.5` according to the RFC7231. This equates"
+ " or multiple types as `application/json, application/xml; q=0.5` according to the RFC7231. This equates"
+ " to the value of `Accept` HTTP header. If set overrides any value found in the OpenApi specification and."
+ " in the component configuration",
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 8304028d1eb..d9873587b2f 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
@@ -123,7 +123,7 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came
HttpHelper.evalPlaceholders(exchange.getMessage().getHeaders(), uri, rcp.getConsumerPath());
// process the incoming request
- return restOpenapiProcessorStrategy.process(o, verb, uri, rcp.getBinding(), exchange, callback);
+ return restOpenapiProcessorStrategy.process(openAPI, o, verb, uri, rcp.getBinding(), exchange, callback);
}
// is it the api-context path
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 52c71a7c671..d93d0a79557 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
@@ -66,6 +66,7 @@ public interface RestOpenapiProcessorStrategy {
/**
* Strategy for processing the Rest DSL operation
*
+ * @param openAPI the openapi specification
* @param operation the rest operation
* @param verb the HTTP verb (GET, POST etc.)
* @param path the context-path
@@ -77,7 +78,7 @@ public interface RestOpenapiProcessorStrategy {
* @return (doneSync) true to continue execute synchronously, false to continue being executed
* asynchronously
*/
- boolean process(
+ boolean process(OpenAPI openAPI,
Operation operation, String verb, String path,
RestBindingAdvice binding,
Exchange exchange, AsyncCallback callback);
diff --git a/core/camel-api/src/generated/java/org/apache/camel/ExchangeConstantProvider.java b/core/camel-api/src/generated/java/org/apache/camel/ExchangeConstantProvider.java
index a97e9e8fc89..1887de93403 100644
--- a/core/camel-api/src/generated/java/org/apache/camel/ExchangeConstantProvider.java
+++ b/core/camel-api/src/generated/java/org/apache/camel/ExchangeConstantProvider.java
@@ -13,7 +13,7 @@ public class ExchangeConstantProvider {
private static final Map<String, String> MAP;
static {
- Map<String, String> map = new HashMap<>(155);
+ Map<String, String> map = new HashMap<>(156);
map.put("ACCEPT_CONTENT_TYPE", "CamelAcceptContentType");
map.put("AGGREGATED_COLLECTION_GUARD", "CamelAggregatedCollectionGuard");
map.put("AGGREGATED_COMPLETED_BY", "CamelAggregatedCompletedBy");
@@ -132,6 +132,7 @@ public class ExchangeConstantProvider {
map.put("REDELIVERY_MAX_COUNTER", "CamelRedeliveryMaxCounter");
map.put("REST_HTTP_QUERY", "CamelRestHttpQuery");
map.put("REST_HTTP_URI", "CamelRestHttpUri");
+ map.put("REST_OPENAPI", "CamelRestOpenAPI");
map.put("REUSE_SCRIPT_ENGINE", "CamelReuseScripteEngine");
map.put("ROLLBACK_ONLY", "CamelRollbackOnly");
map.put("ROLLBACK_ONLY_LAST", "CamelRollbackOnlyLast");
diff --git a/core/camel-api/src/main/java/org/apache/camel/Exchange.java b/core/camel-api/src/main/java/org/apache/camel/Exchange.java
index 13cda74cb76..82d256b5f2d 100644
--- a/core/camel-api/src/main/java/org/apache/camel/Exchange.java
+++ b/core/camel-api/src/main/java/org/apache/camel/Exchange.java
@@ -260,6 +260,7 @@ public interface Exchange extends VariableAware {
String REDELIVERY_DELAY = "CamelRedeliveryDelay";
String REST_HTTP_URI = "CamelRestHttpUri";
String REST_HTTP_QUERY = "CamelRestHttpQuery";
+ String REST_OPENAPI = "CamelRestOpenAPI";
@Deprecated(since = "3.1.0")
String ROLLBACK_ONLY = "CamelRollbackOnly";
@Deprecated(since = "3.1.0")
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/processor/RestBindingAdvice.java b/core/camel-support/src/main/java/org/apache/camel/support/processor/RestBindingAdvice.java
index 32b5bc27775..93e76403335 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/processor/RestBindingAdvice.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/processor/RestBindingAdvice.java
@@ -16,6 +16,8 @@
*/
package org.apache.camel.support.processor;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
index 44adbafbbed..70173163f09 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/RestOpenApiEndpointBuilderFactory.java
@@ -92,9 +92,11 @@ public interface RestOpenApiEndpointBuilderFactory {
/**
* What payload type this component capable of consuming. Could be one
* type, like application/json or multiple types as application/json,
- * application/xml; q=0.5 according to the RFC7231. This equates to the
- * value of Accept HTTP header. If set overrides any value found in the
- * OpenApi specification and. in the component configuration.
+ * application/xml; q=0.5 according to the RFC7231. This equates or
+ * multiple types as application/json, application/xml; q=0.5 according
+ * to the RFC7231. This equates to the value of Accept HTTP header. If
+ * set overrides any value found in the OpenApi specification and. in
+ * the component configuration.
*
* The option is a: <code>java.lang.String</code> type.
*
diff --git a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
index 8aa50678a4a..6d209ef1058 100644
--- a/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
+++ b/dsl/camel-kotlin-api/src/generated/kotlin/org/apache/camel/kotlin/components/RestOpenapiUriDsl.kt
@@ -95,7 +95,8 @@ public class RestOpenapiUriDsl(
/**
* What payload type this component capable of consuming. Could be one type, like application/json
* or multiple types as application/json, application/xml; q=0.5 according to the RFC7231. This
- * equates to the value of Accept HTTP header. If set overrides any value found in the OpenApi
+ * equates or multiple types as application/json, application/xml; q=0.5 according to the RFC7231.
+ * This equates to the value of Accept HTTP header. If set overrides any value found in the OpenApi
* specification and. in the component configuration
*/
public fun consumes(consumes: String) {