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/5c061e7e Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/5c061e7e Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/5c061e7e Branch: refs/heads/master Commit: 5c061e7e68c8cc01206536320b7cce578d5af1c9 Parents: 6012ddc Author: Claus Ibsen <[email protected]> Authored: Fri Aug 26 15:12:59 2016 +0200 Committer: Claus Ibsen <[email protected]> Committed: Fri Aug 26 16:53:31 2016 +0200 ---------------------------------------------------------------------- .../camel/component/rest/RestComponent.java | 10 ++-- .../camel/component/rest/RestEndpoint.java | 2 +- .../apache/camel/spi/RestProducerFactory.java | 4 +- .../common/HttpRestHeaderFilterStrategy.java | 56 ++++++++++++++++++ .../component/jetty/JettyHttpComponent.java | 15 +++-- .../rest/producer/JettyRestProducerGetTest.java | 34 ++++++----- .../JettyRestProducerGetUriParameterTest.java | 59 +++++++++++++++++++ .../netty4/http/NettyHttpComponent.java | 12 ++-- .../http/NettyHttpRestHeaderFilterStrategy.java | 60 ++++++++++++++++++++ .../http/rest/RestNettyProducerGetTest.java | 3 +- .../RestNettyProducerGetUriParameterTest.java | 60 ++++++++++++++++++++ .../component/restlet/RestletComponent.java | 2 +- .../RestRestletProducerGetUriParameterTest.java | 60 ++++++++++++++++++++ .../component/undertow/UndertowComponent.java | 11 ++-- .../UndertowRestHeaderFilterStrategy.java | 56 ++++++++++++++++++ ...RestUndertowProducerGetUriParameterTest.java | 59 +++++++++++++++++++ 16 files changed, 463 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java index d5c471c..f8245c6 100644 --- a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java +++ b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java @@ -59,14 +59,14 @@ public class RestComponent extends UriEndpointComponent { } answer.setHost(h); - setProperties(answer, parameters); - answer.setParameters(parameters); - // the rest is URI parameters on path - String query = URISupport.createQueryString(parameters); - if (ObjectHelper.isNotEmpty(query)) { + String query = ObjectHelper.after(uri, "?"); + if (query != null) { answer.setQueryParameters(query); } + setProperties(answer, parameters); + answer.setParameters(parameters); + if (!remaining.contains(":")) { throw new IllegalArgumentException("Invalid syntax. Must be rest:method:path[:uriTemplate] where uriTemplate is optional"); } http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/camel-core/src/main/java/org/apache/camel/component/rest/RestEndpoint.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/component/rest/RestEndpoint.java b/camel-core/src/main/java/org/apache/camel/component/rest/RestEndpoint.java index daaa459..741c408 100644 --- a/camel-core/src/main/java/org/apache/camel/component/rest/RestEndpoint.java +++ b/camel-core/src/main/java/org/apache/camel/component/rest/RestEndpoint.java @@ -316,7 +316,7 @@ public class RestEndpoint extends DefaultEndpoint { if (factory != null) { LOG.debug("Using RestProducerFactory: {}", factory); - Producer producer = factory.createProducer(getCamelContext(), host, method, path, uriTemplate, consumes, produces, parameters); + Producer producer = factory.createProducer(getCamelContext(), host, method, path, uriTemplate, queryParameters, consumes, produces, parameters); return new RestProducer(this, producer); } 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/5c061e7e/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 f3ab1f7..23dc995 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 @@ -36,6 +36,7 @@ public interface RestProducerFactory { * @param verb HTTP verb such as GET, POST * @param basePath base path * @param uriTemplate uri template + * @param queryParameters uri 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 @@ -43,5 +44,6 @@ public interface RestProducerFactory { * @throws Exception can be thrown */ Producer createProducer(CamelContext camelContext, String host, - String verb, String basePath, String uriTemplate, String consumes, String produces, Map<String, Object> parameters) throws Exception; + String verb, String basePath, String uriTemplate, String queryParameters, + String consumes, String produces, Map<String, Object> parameters) throws Exception; } http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpRestHeaderFilterStrategy.java ---------------------------------------------------------------------- diff --git a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpRestHeaderFilterStrategy.java b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpRestHeaderFilterStrategy.java new file mode 100644 index 0000000..762fe03 --- /dev/null +++ b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpRestHeaderFilterStrategy.java @@ -0,0 +1,56 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.http.common; + +import org.apache.camel.Exchange; + +public class HttpRestHeaderFilterStrategy extends HttpHeaderFilterStrategy { + + private final String templateUri; + private final String queryParameters; + + public HttpRestHeaderFilterStrategy(String templateUri, String queryParameters) { + super(); + this.templateUri = templateUri; + this.queryParameters = queryParameters; + } + + @Override + public boolean applyFilterToCamelHeaders(String headerName, Object headerValue, Exchange exchange) { + boolean answer = super.applyFilterToExternalHeaders(headerName, headerValue, exchange); + // using rest producer then headers are mapping to uri and query parameters using {key} syntax + // if there is a match to an existing Camel Message header, then we should filter (=true) this + // header as its already been mapped by the RestProducer from camel-core, and we do not want + // the header to included as HTTP header also (eg as duplicate value) + if (!answer) { + if (templateUri != null) { + String token = "{" + headerName + "}"; + if (templateUri.contains(token)) { + answer = true; + } + } + if (!answer && queryParameters != null) { + String token = "=%7B" + headerName + "%7D"; // encoded values for { } + if (queryParameters.contains(token)) { + answer = true; + } + } + } + return answer; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/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 3f1ea94..9c79767 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 @@ -38,7 +38,6 @@ import javax.servlet.http.HttpServletResponse; import org.apache.camel.CamelContext; import org.apache.camel.Consumer; import org.apache.camel.Endpoint; -import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.RuntimeCamelException; @@ -48,6 +47,7 @@ import org.apache.camel.http.common.HttpCommonComponent; import org.apache.camel.http.common.HttpCommonEndpoint; import org.apache.camel.http.common.HttpConfiguration; import org.apache.camel.http.common.HttpConsumer; +import org.apache.camel.http.common.HttpRestHeaderFilterStrategy; import org.apache.camel.http.common.HttpRestServletResolveConsumerStrategy; import org.apache.camel.http.common.UrlRewrite; import org.apache.camel.spi.HeaderFilterStrategy; @@ -63,7 +63,6 @@ import org.apache.camel.util.HostUtils; import org.apache.camel.util.IntrospectionSupport; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.ServiceHelper; -import org.apache.camel.util.StringHelper; import org.apache.camel.util.URISupport; import org.apache.camel.util.UnsafeUriCharactersEncoder; import org.apache.camel.util.jsse.SSLContextParameters; @@ -1156,7 +1155,7 @@ public abstract class JettyHttpComponent extends HttpCommonComponent implements @Override public Producer createProducer(CamelContext camelContext, String host, - String verb, String basePath, String uriTemplate, + String verb, String basePath, String uriTemplate, String queryParameters, String consumes, String produces, Map<String, Object> parameters) throws Exception { // avoid leading slash @@ -1164,13 +1163,19 @@ public abstract class JettyHttpComponent extends HttpCommonComponent implements uriTemplate = FileUtil.stripLeadingSeparator(uriTemplate); // get the endpoint - String url = "jetty:%s/%s/%s"; - url = String.format(url, host, basePath, uriTemplate); + String url; + if (uriTemplate != null) { + url = String.format("jetty:%s/%s/%s", host, basePath, uriTemplate); + } else { + url = String.format("jetty:%s/%s", host, basePath); + } JettyHttpEndpoint endpoint = camelContext.getEndpoint(url, JettyHttpEndpoint.class); if (parameters != null && !parameters.isEmpty()) { setProperties(camelContext, endpoint, parameters); } + String path = uriTemplate != null ? uriTemplate : basePath; + endpoint.setHeaderFilterStrategy(new HttpRestHeaderFilterStrategy(path, queryParameters)); return endpoint.createProducer(); } http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetTest.java ---------------------------------------------------------------------- diff --git a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetTest.java b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetTest.java index 58720cd..89c19cf 100644 --- a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetTest.java +++ b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetTest.java @@ -16,6 +16,8 @@ */ package org.apache.camel.component.jetty.rest.producer; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; import org.apache.camel.RoutesBuilder; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.jetty.BaseJettyTest; @@ -24,27 +26,33 @@ import org.junit.Test; public class JettyRestProducerGetTest extends BaseJettyTest { @Test - public void testRestGet() throws Exception { - getMockEndpoint("mock:result").expectedBodiesReceived("Hello Donald Duck"); - - template.sendBodyAndHeader("direct:start", null, "name", "Donald Duck"); - - assertMockEndpointsSatisfied(); + public void testJettyProducerGet() throws Exception { + String out = fluentTemplate.withHeader("id", "123").to("direct:start").request(String.class); + assertEquals("123;Donald Duck", out); } @Override - protected RoutesBuilder createRouteBuilder() throws Exception { + protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { - restConfiguration().producerComponent("jetty").host("localhost").port(getPort()); + // configure to use localhost with the given port + restConfiguration().component("jetty").host("localhost").port(getPort()); from("direct:start") - .to("rest:get:api:hello/hi/{name}") - .to("mock:result"); - - from("jetty:http://localhost:{{port}}/api/hello/hi/?matchOnUriPrefix=true") - .transform().constant("Hello Donald Duck"); + .to("rest:get:users/{id}/basic"); + + // use the rest DSL to define the rest services + rest("/users/") + .get("{id}/basic") + .route() + .to("mock:input") + .process(new Processor() { + public void process(Exchange exchange) throws Exception { + String id = exchange.getIn().getHeader("id", String.class); + exchange.getOut().setBody(id + ";Donald Duck"); + } + }); } }; } http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetUriParameterTest.java ---------------------------------------------------------------------- diff --git a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetUriParameterTest.java b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetUriParameterTest.java new file mode 100644 index 0000000..efa8975 --- /dev/null +++ b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetUriParameterTest.java @@ -0,0 +1,59 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.jetty.rest.producer; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.jetty.BaseJettyTest; +import org.junit.Test; + +public class JettyRestProducerGetUriParameterTest extends BaseJettyTest { + + @Test + public void testJettyProducerGet() throws Exception { + String out = fluentTemplate.withHeader("id", "123").to("direct:start").request(String.class); + assertEquals("123;Donald Duck", out); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + // configure to use localhost with the given port + restConfiguration().component("jetty").host("localhost").port(getPort()); + + from("direct:start") + .to("rest:get:users/basic?id={id}"); + + // use the rest DSL to define the rest services + rest("/users/") + .get("basic/?id={id}") + .route() + .to("mock:input") + .process(new Processor() { + public void process(Exchange exchange) throws Exception { + String id = exchange.getIn().getHeader("id", String.class); + exchange.getOut().setBody(id + ";Donald Duck"); + } + }); + } + }; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java index c623250..5cbea53 100644 --- a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java +++ b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java @@ -381,28 +381,28 @@ public class NettyHttpComponent extends NettyComponent implements HeaderFilterSt @Override public Producer createProducer(CamelContext camelContext, String host, - String verb, String basePath, String uriTemplate, + String verb, String basePath, String uriTemplate, String queryParameters, String consumes, String produces, Map<String, Object> parameters) throws Exception { // avoid leading slash basePath = FileUtil.stripLeadingSeparator(basePath); uriTemplate = FileUtil.stripLeadingSeparator(uriTemplate); - // restlet method must be in upper-case - String restletMethod = verb.toUpperCase(Locale.US); - // get the endpoint String url; if (uriTemplate != null) { - url = String.format("netty4-http:%s/%s/%s?restletMethods=%s", host, basePath, uriTemplate, restletMethod); + url = String.format("netty4-http:%s/%s/%s", host, basePath, uriTemplate); } else { - url = String.format("netty4-http:%s/%s?restletMethods=%s", host, basePath, restletMethod); + url = String.format("netty4-http:%s/%s", host, basePath); } + NettyHttpEndpoint endpoint = camelContext.getEndpoint(url, NettyHttpEndpoint.class); if (parameters != null && !parameters.isEmpty()) { setProperties(camelContext, endpoint, parameters); } + String path = uriTemplate != null ? uriTemplate : basePath; + endpoint.setHeaderFilterStrategy(new NettyHttpRestHeaderFilterStrategy(path, queryParameters)); // the endpoint must be started before creating the producer ServiceHelper.startService(endpoint); http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpRestHeaderFilterStrategy.java ---------------------------------------------------------------------- diff --git a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpRestHeaderFilterStrategy.java b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpRestHeaderFilterStrategy.java new file mode 100644 index 0000000..c168ed0 --- /dev/null +++ b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpRestHeaderFilterStrategy.java @@ -0,0 +1,60 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.netty4.http; + +import org.apache.camel.Exchange; +import org.apache.camel.spi.HeaderFilterStrategy; + +/** + * Default Netty {@link HeaderFilterStrategy} used when binding with {@link NettyHttpBinding}. + */ +public class NettyHttpRestHeaderFilterStrategy extends NettyHttpHeaderFilterStrategy { + + private final String templateUri; + private final String queryParameters; + + public NettyHttpRestHeaderFilterStrategy(String templateUri, String queryParameters) { + super(); + this.templateUri = templateUri; + this.queryParameters = queryParameters; + } + + @Override + public boolean applyFilterToCamelHeaders(String headerName, Object headerValue, Exchange exchange) { + boolean answer = super.applyFilterToExternalHeaders(headerName, headerValue, exchange); + // using rest producer then headers are mapping to uri and query parameters using {key} syntax + // if there is a match to an existing Camel Message header, then we should filter (=true) this + // header as its already been mapped by the RestProducer from camel-core, and we do not want + // the header to included as HTTP header also (eg as duplicate value) + if (!answer) { + if (templateUri != null) { + String token = "{" + headerName + "}"; + if (templateUri.contains(token)) { + answer = true; + } + } + if (!answer && queryParameters != null) { + String token = "=%7B" + headerName + "%7D"; // encoded values for { } + if (queryParameters.contains(token)) { + answer = true; + } + } + } + return answer; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/rest/RestNettyProducerGetTest.java ---------------------------------------------------------------------- diff --git a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/rest/RestNettyProducerGetTest.java b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/rest/RestNettyProducerGetTest.java index bcef723..d97214d 100644 --- a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/rest/RestNettyProducerGetTest.java +++ b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/rest/RestNettyProducerGetTest.java @@ -28,8 +28,7 @@ public class RestNettyProducerGetTest extends BaseNettyTest { public void testNettyProducerGet() throws Exception { String out = fluentTemplate.withHeader("id", "123").to("direct:start").request(String.class); assertNotNull(out); - // TODO: [123, 123];Donald Duck - // assertEquals("123;Donald Duck", out); + assertEquals("123;Donald Duck", out); } @Override http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/rest/RestNettyProducerGetUriParameterTest.java ---------------------------------------------------------------------- diff --git a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/rest/RestNettyProducerGetUriParameterTest.java b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/rest/RestNettyProducerGetUriParameterTest.java new file mode 100644 index 0000000..f42e28b --- /dev/null +++ b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/rest/RestNettyProducerGetUriParameterTest.java @@ -0,0 +1,60 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.netty4.http.rest; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.netty4.http.BaseNettyTest; +import org.junit.Test; + +public class RestNettyProducerGetUriParameterTest extends BaseNettyTest { + + @Test + public void testNettyProducerGet() throws Exception { + String out = fluentTemplate.withHeader("id", "123").to("direct:start").request(String.class); + assertNotNull(out); + assertEquals("123;Donald Duck", out); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + // configure to use netty on localhost with the given port + restConfiguration().component("netty4-http").host("localhost").port(getPort()); + + from("direct:start") + .to("rest:get:users/basic/?id={id}"); + + // use the rest DSL to define the rest services + rest("/users/") + .get("basic/?id={id}") + .route() + .to("mock:input") + .process(new Processor() { + public void process(Exchange exchange) throws Exception { + String id = exchange.getIn().getHeader("id", String.class); + exchange.getOut().setBody(id + ";Donald Duck"); + } + }); + } + }; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletComponent.java b/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletComponent.java index 4a29ff0..fdbca18 100644 --- a/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletComponent.java +++ b/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletComponent.java @@ -809,7 +809,7 @@ public class RestletComponent extends HeaderFilterStrategyComponent implements R @Override public Producer createProducer(CamelContext camelContext, String host, - String verb, String basePath, String uriTemplate, + String verb, String basePath, String uriTemplate, String queryParameters, String consumes, String produces, Map<String, Object> parameters) throws Exception { // avoid leading slash http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletProducerGetUriParameterTest.java ---------------------------------------------------------------------- diff --git a/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletProducerGetUriParameterTest.java b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletProducerGetUriParameterTest.java new file mode 100644 index 0000000..e875af1 --- /dev/null +++ b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletProducerGetUriParameterTest.java @@ -0,0 +1,60 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.restlet; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.junit.Test; + +/** + * @version + */ +public class RestRestletProducerGetUriParameterTest extends RestletTestSupport { + + @Test + public void testRestletProducerGet() throws Exception { + String out = fluentTemplate.withHeader("id", "123").to("direct:start").request(String.class); + assertEquals("123;Donald Duck", out); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + // configure to use restlet on localhost with the given port + restConfiguration().component("restlet").host("localhost").port(portNum); + + from("direct:start") + .to("rest:get:users/basic?id={id}"); + + // use the rest DSL to define the rest services + rest("/users/") + .get("basic/?id={id}") + .route() + .to("mock:input") + .process(new Processor() { + public void process(Exchange exchange) throws Exception { + String id = exchange.getIn().getHeader("id", String.class); + exchange.getOut().setBody(id + ";Donald Duck"); + } + }); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java index 98cf710..225fd42 100644 --- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java +++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java @@ -235,28 +235,27 @@ public class UndertowComponent extends UriEndpointComponent implements RestConsu @Override public Producer createProducer(CamelContext camelContext, String host, - String verb, String basePath, String uriTemplate, + String verb, String basePath, String uriTemplate, String queryParameters, String consumes, String produces, Map<String, Object> parameters) throws Exception { // avoid leading slash basePath = FileUtil.stripLeadingSeparator(basePath); uriTemplate = FileUtil.stripLeadingSeparator(uriTemplate); - // restlet method must be in upper-case - String restletMethod = verb.toUpperCase(Locale.US); - // get the endpoint String url; if (uriTemplate != null) { - url = String.format("undertow:%s/%s/%s?restletMethods=%s", host, basePath, uriTemplate, restletMethod); + url = String.format("undertow:%s/%s/%s", host, basePath, uriTemplate); } else { - url = String.format("undertow:%s/%s?restletMethods=%s", host, basePath, restletMethod); + url = String.format("undertow:%s/%s", host, basePath); } UndertowEndpoint endpoint = camelContext.getEndpoint(url, UndertowEndpoint.class); if (parameters != null && !parameters.isEmpty()) { setProperties(camelContext, endpoint, parameters); } + String path = uriTemplate != null ? uriTemplate : basePath; + endpoint.setHeaderFilterStrategy(new UndertowRestHeaderFilterStrategy(path, queryParameters)); // the endpoint must be started before creating the producer ServiceHelper.startService(endpoint); http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowRestHeaderFilterStrategy.java ---------------------------------------------------------------------- diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowRestHeaderFilterStrategy.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowRestHeaderFilterStrategy.java new file mode 100644 index 0000000..a091d62 --- /dev/null +++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowRestHeaderFilterStrategy.java @@ -0,0 +1,56 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.undertow; + +import org.apache.camel.Exchange; + +public class UndertowRestHeaderFilterStrategy extends UndertowHeaderFilterStrategy { + + private final String templateUri; + private final String queryParameters; + + public UndertowRestHeaderFilterStrategy(String templateUri, String queryParameters) { + super(); + this.templateUri = templateUri; + this.queryParameters = queryParameters; + } + + @Override + public boolean applyFilterToCamelHeaders(String headerName, Object headerValue, Exchange exchange) { + boolean answer = super.applyFilterToExternalHeaders(headerName, headerValue, exchange); + // using rest producer then headers are mapping to uri and query parameters using {key} syntax + // if there is a match to an existing Camel Message header, then we should filter (=true) this + // header as its already been mapped by the RestProducer from camel-core, and we do not want + // the header to included as HTTP header also (eg as duplicate value) + if (!answer) { + if (templateUri != null) { + String token = "{" + headerName + "}"; + if (templateUri.contains(token)) { + answer = true; + } + } + if (!answer && queryParameters != null) { + String token = "=%7B" + headerName + "%7D"; // encoded values for { } + if (queryParameters.contains(token)) { + answer = true; + } + } + } + return answer; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/5c061e7e/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowProducerGetUriParameterTest.java ---------------------------------------------------------------------- diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowProducerGetUriParameterTest.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowProducerGetUriParameterTest.java new file mode 100644 index 0000000..10466c6 --- /dev/null +++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowProducerGetUriParameterTest.java @@ -0,0 +1,59 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.undertow.rest; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.undertow.BaseUndertowTest; +import org.junit.Test; + +public class RestUndertowProducerGetUriParameterTest extends BaseUndertowTest { + + @Test + public void testUndertowProducerGet() throws Exception { + String out = fluentTemplate.withHeader("id", "123").to("direct:start").request(String.class); + assertEquals("123;Donald Duck", out); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + // configure to use undertow on localhost with the given port + restConfiguration().component("undertow").host("localhost").port(getPort()); + + from("direct:start") + .to("rest:get:users/basic?id={id}"); + + // use the rest DSL to define the rest services + rest("/users/") + .get("basic/?id={id}") + .route() + .to("mock:input") + .process(new Processor() { + public void process(Exchange exchange) throws Exception { + String id = exchange.getIn().getHeader("id", String.class); + exchange.getOut().setBody(id + ";Donald Duck"); + } + }); + } + }; + } + +}
