CAMEL-10164: swagger component for making rest calls with swagger schema validation and facade to actual HTTP client in use
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/56b31520 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/56b31520 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/56b31520 Branch: refs/heads/master Commit: 56b31520f3d9fc3ebdb2bffc146dc4bd6f15f34b Parents: b2508f1 Author: Claus Ibsen <[email protected]> Authored: Wed Aug 24 15:23:22 2016 +0200 Committer: Claus Ibsen <[email protected]> Committed: Fri Aug 26 16:53:31 2016 +0200 ---------------------------------------------------------------------- .../apache/camel/spi/RestProducerFactory.java | 25 ++++---- .../component/jetty/JettyHttpComponent.java | 12 ++-- .../src/test/resources/log4j2.properties | 1 - .../swagger/component/SwaggerProducer.java | 65 +++++++++++--------- .../component/DummyRestProducerFactory.java | 2 +- 5 files changed, 56 insertions(+), 49 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/56b31520/camel-core/src/main/java/org/apache/camel/spi/RestProducerFactory.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/spi/RestProducerFactory.java b/camel-core/src/main/java/org/apache/camel/spi/RestProducerFactory.java index 5da1261..255ea6a 100644 --- a/camel-core/src/main/java/org/apache/camel/spi/RestProducerFactory.java +++ b/camel-core/src/main/java/org/apache/camel/spi/RestProducerFactory.java @@ -31,21 +31,22 @@ public interface RestProducerFactory { /** * Creates a new REST producer. * - * @param camelContext the camel context - * @param exchange the exchange - * @param scheme scheme to use such as http or https - * @param host host (incl port) of the REST service - * @param verb HTTP verb such as GET, POST - * @param basePath base path - * @param uriTemplate uri template - * @param queryParameters query parameters - * @param consumes media-types for what the REST service consume as input (accept-type), is <tt>null</tt> or <tt>*/*</tt> for anything - * @param produces media-types for what the REST service produces as output, can be <tt>null</tt> - * @param parameters additional parameters + * @param camelContext the camel context + * @param exchange the exchange + * @param scheme scheme to use such as http or https + * @param host host (incl port) of the REST service + * @param verb HTTP verb such as GET, POST + * @param basePath base path + * @param uriTemplate uri template + * @param resolvedUriTemplate uri template where path parameters has been resolved + * @param queryParameters query parameters + * @param consumes media-types for what the REST service consume as input (accept-type), is <tt>null</tt> or <tt>*/*</tt> for anything + * @param produces media-types for what the REST service produces as output, can be <tt>null</tt> + * @param parameters additional parameters * @return a newly created REST producer * @throws Exception can be thrown */ Producer createProducer(CamelContext camelContext, Exchange exchange, String scheme, String host, - String verb, String basePath, String uriTemplate, String queryParameters, + String verb, String basePath, String uriTemplate, String resolvedUriTemplate, String queryParameters, String consumes, String produces, Map<String, Object> parameters) throws Exception; } http://git-wip-us.apache.org/repos/asf/camel/blob/56b31520/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java index b1972fc..9ba3f04 100644 --- a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java +++ b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java @@ -1152,19 +1152,17 @@ public abstract class JettyHttpComponent extends HttpCommonComponent implements @Override public Producer createProducer(CamelContext camelContext, Exchange exchange, String scheme, String host, - String verb, String basePath, String uriTemplate, String queryParameters, + String verb, String basePath, String uriTemplate, String resolvedUriTemplate, String queryParameters, String consumes, String produces, Map<String, Object> parameters) throws Exception { // avoid leading slash basePath = FileUtil.stripLeadingSeparator(basePath); uriTemplate = FileUtil.stripLeadingSeparator(uriTemplate); - // does the uri template use placeholders? - if (uriTemplate.contains("{")) { - // us a header for the dynamic uri template so we reuse same endpoint - // TODO: fix me later - String path = StringHelper.replaceAll(uriTemplate, "{name}", "Donald Duck"); - String overrideUri = String.format("%s://%s/%s/%s", scheme, host, basePath, path); + // does the uri template use path parameters? + if (uriTemplate.contains("{") && resolvedUriTemplate != null) { + // if so us a header for the dynamic uri template so we reuse same endpoint but the header overrides the actual url to use + String overrideUri = String.format("%s://%s/%s/%s", scheme, host, basePath, resolvedUriTemplate); exchange.getIn().setHeader(Exchange.HTTP_URI, overrideUri); } http://git-wip-us.apache.org/repos/asf/camel/blob/56b31520/components/camel-jetty9/src/test/resources/log4j2.properties ---------------------------------------------------------------------- diff --git a/components/camel-jetty9/src/test/resources/log4j2.properties b/components/camel-jetty9/src/test/resources/log4j2.properties index b91c7b3..c863dc3 100644 --- a/components/camel-jetty9/src/test/resources/log4j2.properties +++ b/components/camel-jetty9/src/test/resources/log4j2.properties @@ -25,5 +25,4 @@ appender.out.name = out appender.out.layout.type = PatternLayout appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n rootLogger.level = INFO -rootLogger.appenderRef.out.ref = out rootLogger.appenderRef.file.ref = file http://git-wip-us.apache.org/repos/asf/camel/blob/56b31520/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/component/SwaggerProducer.java ---------------------------------------------------------------------- diff --git a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/component/SwaggerProducer.java b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/component/SwaggerProducer.java index 1456dc5..e410e28 100644 --- a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/component/SwaggerProducer.java +++ b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/component/SwaggerProducer.java @@ -38,6 +38,7 @@ import org.apache.camel.spi.RestProducerFactory; import org.apache.camel.util.AsyncProcessorConverterHelper; import org.apache.camel.util.CollectionStringBuffer; import org.apache.camel.util.ServiceHelper; +import org.apache.camel.util.StringHelper; import org.apache.camel.util.URISupport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,36 +71,12 @@ public class SwaggerProducer extends DefaultAsyncProducer { } try { - Map<String, Object> query = new LinkedHashMap<>(); - for (Parameter param : operation.getParameters()) { - if ("query".equals(param.getIn())) { - String name = param.getName(); - if (name != null) { - String value = exchange.getIn().getHeader(name, String.class); - if (value != null) { - query.put(name, value); - } else if (param.getRequired()) { - // the parameter is required but there is no header with the value - exchange.setException(new NoSuchHeaderException(exchange, name, String.class)); - callback.done(true); - return true; - } - } - } - } - - // build as query string - String options = null; - if (!query.isEmpty()) { - options = URISupport.createQueryString(query); - } - // TODO: bind to consumes context-type // TODO: if binding is turned on/off/auto etc // TODO: build dynamic uri for component (toD, headers) // create http producer to use for calling the remote HTTP service // TODO: create the producer once and reuse (create HTTP_XXX headers for dynamic values) - Producer producer = createHttpProducer(exchange, operation, verb, path, options); + Producer producer = createHttpProducer(exchange, operation, verb, path); if (producer != null) { ServiceHelper.startService(producer); AsyncProcessor async = AsyncProcessorConverterHelper.convert(producer); @@ -149,7 +126,7 @@ public class SwaggerProducer extends DefaultAsyncProducer { this.swagger = swagger; } - protected Producer createHttpProducer(Exchange exchange, Operation operation, String verb, String path, String queryParameters) throws Exception { + protected Producer createHttpProducer(Exchange exchange, Operation operation, String verb, String path) throws Exception { RestProducerFactory factory = null; String cname = null; if (getEndpoint().getComponentName() != null) { @@ -222,8 +199,40 @@ public class SwaggerProducer extends DefaultAsyncProducer { String basePath = swagger.getBasePath(); String uriTemplate = path; - return factory.createProducer(getEndpoint().getCamelContext(), exchange, scheme, host, verb, basePath, uriTemplate, queryParameters, - (consumes.isEmpty() ? "" : consumes.toString()), (produces.isEmpty() ? "" : produces.toString()), null); + // uri template with path parameters resolved + String resolvedUriTemplate = uriTemplate; + // for query parameters + Map<String, Object> query = new LinkedHashMap<>(); + for (Parameter param : operation.getParameters()) { + if ("query".equals(param.getIn())) { + String name = param.getName(); + if (name != null) { + String value = exchange.getIn().getHeader(name, String.class); + if (value != null) { + query.put(name, value); + } else if (param.getRequired()) { + throw new NoSuchHeaderException(exchange, name, String.class); + } + } + } else if ("path".equals(param.getIn())) { + String value = exchange.getIn().getHeader(param.getName(), String.class); + if (value != null) { + String token = "{" + param.getName() + "}"; + resolvedUriTemplate = StringHelper.replaceAll(resolvedUriTemplate, token, value); + } else if (param.getRequired()) { + // the parameter is required but we do not have a header + throw new NoSuchHeaderException(exchange, param.getName(), String.class); + } + } + } + // build as query string + String queryParameters = null; + if (!query.isEmpty()) { + queryParameters = URISupport.createQueryString(query); + } + + return factory.createProducer(getEndpoint().getCamelContext(), exchange, scheme, host, verb, basePath, uriTemplate, resolvedUriTemplate, + queryParameters, (consumes.isEmpty() ? "" : consumes.toString()), (produces.isEmpty() ? "" : produces.toString()), null); } else { throw new IllegalStateException("Cannot find RestProducerFactory in Registry or as a Component to use"); http://git-wip-us.apache.org/repos/asf/camel/blob/56b31520/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/component/DummyRestProducerFactory.java ---------------------------------------------------------------------- diff --git a/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/component/DummyRestProducerFactory.java b/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/component/DummyRestProducerFactory.java index d092f16..096b440 100644 --- a/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/component/DummyRestProducerFactory.java +++ b/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/component/DummyRestProducerFactory.java @@ -29,7 +29,7 @@ public class DummyRestProducerFactory implements RestProducerFactory { @Override public Producer createProducer(CamelContext camelContext, Exchange exchange, String scheme, String host, - String verb, String basePath, final String uriTemplate, final String queryParameters, + String verb, String basePath, final String uriTemplate, final String resolvedUriTemplate, final String queryParameters, String consumes, String produces, Map<String, Object> parameters) throws Exception { // use a dummy endpoint
