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 a32952c631a4aed00709409bc4eaddd8c2eb5957 Author: Claus Ibsen <[email protected]> AuthorDate: Wed Mar 27 09:46:49 2024 +0100 CAMEL-20557: Rest DSL to use openapi spec directly --- components/camel-rest-openapi/pom.xml | 4 ++ .../DefaultRestOpenapiProcessorStrategy.java | 27 ++++++++++++ .../rest/openapi/RestOpenApiEndpoint.java | 48 ++-------------------- .../component/rest/openapi/RestOpenApiHelper.java | 44 ++++++++++++++++++++ .../rest/openapi/RestOpenApiProcessor.java | 15 ++----- 5 files changed, 82 insertions(+), 56 deletions(-) diff --git a/components/camel-rest-openapi/pom.xml b/components/camel-rest-openapi/pom.xml index 47b7d883b14..26decde74ba 100644 --- a/components/camel-rest-openapi/pom.xml +++ b/components/camel-rest-openapi/pom.xml @@ -48,6 +48,10 @@ <groupId>org.apache.camel</groupId> <artifactId>camel-rest</artifactId> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-platform-http</artifactId> + </dependency> <dependency> <groupId>io.swagger.core.v3</groupId> 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 4d1640e569a..2f4c9eaa996 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 @@ -23,6 +23,7 @@ import java.util.stream.Collectors; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; +import joptsimple.internal.Strings; import org.apache.camel.AsyncCallback; import org.apache.camel.AsyncProducer; import org.apache.camel.CamelContext; @@ -32,6 +33,7 @@ import org.apache.camel.Exchange; import org.apache.camel.NonManagedService; import org.apache.camel.Route; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.component.platform.http.PlatformHttpComponent; import org.apache.camel.spi.PackageScanResourceResolver; import org.apache.camel.spi.ProducerCache; import org.apache.camel.spi.Resource; @@ -58,6 +60,7 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport private String component = "direct"; private String missingOperation; private String mockIncludePattern; + private final List<String> uris = new ArrayList<>(); @Override public void validateOpenApi(OpenAPI openAPI) throws Exception { @@ -95,6 +98,24 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport LOG.debug(msg + ". This validation error is ignored (Will return a mocked/empty response)."); } } + + // enlist open-api rest services + PlatformHttpComponent phc = camelContext.getComponent("platform-http", PlatformHttpComponent.class); + if (phc != null) { + String path = RestOpenApiHelper.getBasePathFromOpenApi(openAPI); + if (path == null || path.isEmpty() || path.equals("/")) { + path = ""; + } + for (var p : openAPI.getPaths().entrySet()) { + String uri = path + p.getKey(); + String verbs = Strings.join(p.getValue().readOperationsMap().keySet().stream() + .map(Enum::name) + .sorted() + .collect(Collectors.toList()), ","); + phc.addHttpEndpoint(uri, verbs, null, null, null); + uris.add(uri); + } + } } @Override @@ -236,6 +257,12 @@ public class DefaultRestOpenapiProcessorStrategy extends ServiceSupport @Override protected void doStop() throws Exception { ServiceHelper.stopService(producerCache); + + PlatformHttpComponent phc = camelContext.getComponent("platform-http", PlatformHttpComponent.class); + if (phc != null) { + uris.forEach(phc::removeHttpEndpoint); + uris.clear(); + } } } 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 d01aba71ec7..0ef9aa3703e 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 @@ -30,8 +30,6 @@ import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.function.Function; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -213,7 +211,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint { public Consumer createConsumer(final Processor processor) throws Exception { OpenAPI doc = loadSpecificationFrom(getCamelContext(), specificationUri); String path = determineBasePath(doc); - Processor target = new RestOpenApiProcessor(this, doc, path, processor); + Processor target = new RestOpenApiProcessor(this, doc, path, processor, restOpenapiProcessorStrategy); CamelContextAware.trySetCamelContext(target, getCamelContext()); return createConsumerFor(path, target); } @@ -510,7 +508,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint { return componentBasePath; } - final String specificationBasePath = getBasePathFromOpenApi(openapi); + final String specificationBasePath = RestOpenApiHelper.getBasePathFromOpenApi(openapi); if (isNotEmpty(specificationBasePath)) { return specificationBasePath; @@ -528,46 +526,6 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint { return RestOpenApiComponent.DEFAULT_BASE_PATH; } - public static String getBasePathFromOpenApi(final OpenAPI openApi) { - String basePath = null; - if (openApi.getServers() != null) { - for (Server server : openApi.getServers()) { - if (server.getUrl() != null) { - try { - URI serverUrl = new URI(parseVariables(server.getUrl(), server)); - basePath = serverUrl.getPath(); - // Is this really necessary? - if (basePath.indexOf("//") == 0) { - // strip off the first "/" if double "/" exists - basePath = basePath.substring(1); - } - if ("/".equals(basePath)) { - basePath = ""; - } - } catch (URISyntaxException e) { - //not a valid whole url, just the basePath - basePath = server.getUrl(); - } - } - } - } - return basePath; - } - - public static String parseVariables(String url, Server server) { - Pattern p = Pattern.compile("\\{(.*?)\\}"); - Matcher m = p.matcher(url); - while (m.find()) { - - String variable = m.group(1); - if (server != null && server.getVariables() != null && server.getVariables().get(variable) != null) { - String varValue = server.getVariables().get(variable).getDefault(); - url = url.replace("{" + variable + "}", varValue); - } - } - return url; - } - String determineComponentName() { return Optional.ofNullable(componentName).orElse(getComponent().getComponentName()); } @@ -753,7 +711,7 @@ public final class RestOpenApiEndpoint extends DefaultEndpoint { if (servers != null) { for (Server server : servers) { try { - uris.add(new URI(parseVariables(server.getUrl(), server))); + uris.add(new URI(RestOpenApiHelper.parseVariables(server.getUrl(), server))); } catch (URISyntaxException e) { // ignore } 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 4af6a0772c8..fc8e460c551 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 @@ -16,6 +16,8 @@ */ package org.apache.camel.component.rest.openapi; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -23,6 +25,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.servers.Server; import org.apache.camel.spi.ContentTypeAware; import org.apache.camel.spi.Resource; import org.apache.camel.util.ObjectHelper; @@ -90,4 +94,44 @@ final class RestOpenApiHelper { return location.toLowerCase().endsWith(".yml") || location.toLowerCase().endsWith(".yaml"); } + public static String getBasePathFromOpenApi(final OpenAPI openApi) { + String basePath = null; + if (openApi.getServers() != null) { + for (Server server : openApi.getServers()) { + if (server.getUrl() != null) { + try { + URI serverUrl = new URI(parseVariables(server.getUrl(), server)); + basePath = serverUrl.getPath(); + // Is this really necessary? + if (basePath.indexOf("//") == 0) { + // strip off the first "/" if double "/" exists + basePath = basePath.substring(1); + } + if ("/".equals(basePath)) { + basePath = ""; + } + } catch (URISyntaxException e) { + //not a valid whole url, just the basePath + basePath = server.getUrl(); + } + } + } + } + return basePath; + } + + public static String parseVariables(String url, Server server) { + Pattern p = Pattern.compile("\\{(.*?)\\}"); + Matcher m = p.matcher(url); + while (m.find()) { + + String variable = m.group(1); + if (server != null && server.getVariables() != null && server.getVariables().get(variable) != null) { + String varValue = server.getVariables().get(variable).getDefault(); + url = url.replace("{" + variable + "}", varValue); + } + } + return url; + } + } 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 35aa33035f2..429b01dcd4b 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 @@ -48,14 +48,15 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came private final OpenAPI openAPI; private final String basePath; private final List<RestConsumerContextPathMatcher.ConsumerPath<Operation>> paths = new ArrayList<>(); - private RestOpenapiProcessorStrategy restOpenapiProcessorStrategy; + private final RestOpenapiProcessorStrategy restOpenapiProcessorStrategy; - public RestOpenApiProcessor(RestOpenApiEndpoint endpoint, OpenAPI openAPI, String basePath, Processor processor) { + public RestOpenApiProcessor(RestOpenApiEndpoint endpoint, OpenAPI openAPI, String basePath, Processor processor, + RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) { super(processor); this.endpoint = endpoint; this.basePath = basePath; this.openAPI = openAPI; - this.restOpenapiProcessorStrategy = new DefaultRestOpenapiProcessorStrategy(); + this.restOpenapiProcessorStrategy = restOpenapiProcessorStrategy; } @Override @@ -68,14 +69,6 @@ public class RestOpenApiProcessor extends DelegateAsyncProcessor implements Came this.camelContext = camelContext; } - public RestOpenapiProcessorStrategy getRestOpenapiProcessorStrategy() { - return restOpenapiProcessorStrategy; - } - - public void setRestOpenapiProcessorStrategy(RestOpenapiProcessorStrategy restOpenapiProcessorStrategy) { - this.restOpenapiProcessorStrategy = restOpenapiProcessorStrategy; - } - @Override public boolean process(Exchange exchange, AsyncCallback callback) { String path = exchange.getMessage().getHeader(Exchange.HTTP_PATH, String.class);
