Repository: camel Updated Branches: refs/heads/master 19f27fd26 -> 88b8e447b
CAMEL-9089: rest-dsl when multiple candidates then use the most specific one. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/b1c9132c Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/b1c9132c Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/b1c9132c Branch: refs/heads/master Commit: b1c9132cf22de1c066a9869b2f54235c6ab535dd Parents: 57f48e8 Author: Claus Ibsen <davscl...@apache.org> Authored: Fri Aug 21 10:24:41 2015 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Fri Aug 21 10:53:02 2015 +0200 ---------------------------------------------------------------------- .../HttpServerMultiplexChannelHandler.java | 61 ++++++++++++++- .../rest/RestNettyHttpGetWildcardsTest.java | 79 ++++++++++++++++++++ .../HttpServerMultiplexChannelHandler.java | 2 +- 3 files changed, 138 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/b1c9132c/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/handlers/HttpServerMultiplexChannelHandler.java ---------------------------------------------------------------------- diff --git a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/handlers/HttpServerMultiplexChannelHandler.java b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/handlers/HttpServerMultiplexChannelHandler.java index 2bcac76..747b242 100644 --- a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/handlers/HttpServerMultiplexChannelHandler.java +++ b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/handlers/HttpServerMultiplexChannelHandler.java @@ -203,18 +203,46 @@ public class HttpServerMultiplexChannelHandler extends SimpleChannelUpstreamHand } } - // then match by non wildcard path + // then match by wildcard path if (answer == null) { Iterator<Map.Entry<ContextPathMatcher, HttpServerChannelHandler>> it = candidates.iterator(); while (it.hasNext()) { Map.Entry<ContextPathMatcher, HttpServerChannelHandler> entry = it.next(); + // filter non matching paths if (!entry.getKey().matchesRest(path, true)) { it.remove(); } } - // there should only be one - if (candidates.size() == 1) { + // if there is multiple candidates with wildcards then pick anyone with the least number of wildcards + int bestWildcard = Integer.MAX_VALUE; + Map.Entry<ContextPathMatcher, HttpServerChannelHandler> best = null; + if (candidates.size() > 1) { + it = candidates.iterator(); + while (it.hasNext()) { + Map.Entry<ContextPathMatcher, HttpServerChannelHandler> entry = it.next(); + String consumerPath = entry.getValue().getConsumer().getConfiguration().getPath(); + int wildcards = countWildcards(consumerPath); + if (wildcards > 0) { + if (best == null) { + best = entry; + } else { + if (wildcards < bestWildcard) { + bestWildcard = wildcards; + best = entry; + } + } + } + } + + if (best != null) { + // pick the best among the wildcards + answer = best.getValue(); + } + } + + // if there is one left then its our answer + if (answer == null && candidates.size() == 1) { answer = candidates.get(0).getValue(); } } @@ -232,6 +260,33 @@ public class HttpServerMultiplexChannelHandler extends SimpleChannelUpstreamHand return answer; } + /** + * Counts the number of wildcards in the path + * + * @param consumerPath the consumer path which may use { } tokens + * @return number of wildcards, or <tt>0</tt> if no wildcards + */ + private static int countWildcards(String consumerPath) { + int wildcards = 0; + + // remove starting/ending slashes + if (consumerPath.startsWith("/")) { + consumerPath = consumerPath.substring(1); + } + if (consumerPath.endsWith("/")) { + consumerPath = consumerPath.substring(0, consumerPath.length() - 1); + } + + String[] consumerPaths = consumerPath.split("/"); + for (String p2 : consumerPaths) { + if (p2.startsWith("{") && p2.endsWith("}")) { + wildcards++; + } + } + + return wildcards; + } + private static String pathAsKey(String path) { // cater for default path if (path == null || path.equals("/")) { http://git-wip-us.apache.org/repos/asf/camel/blob/b1c9132c/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/rest/RestNettyHttpGetWildcardsTest.java ---------------------------------------------------------------------- diff --git a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/rest/RestNettyHttpGetWildcardsTest.java b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/rest/RestNettyHttpGetWildcardsTest.java new file mode 100644 index 0000000..403bc8f --- /dev/null +++ b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/rest/RestNettyHttpGetWildcardsTest.java @@ -0,0 +1,79 @@ +/** + * 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.netty.http.rest; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.netty.http.BaseNettyTest; +import org.apache.camel.component.netty.http.RestNettyHttpBinding; +import org.apache.camel.impl.JndiRegistry; +import org.junit.Test; + +public class RestNettyHttpGetWildcardsTest extends BaseNettyTest { + + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry jndi = super.createRegistry(); + jndi.bind("mybinding", new RestNettyHttpBinding()); + return jndi; + } + + @Test + public void testProducerGet() throws Exception { + String out = template.requestBody("netty-http:http://localhost:{{port}}/users/123/basic", null, String.class); + assertEquals("123;Donald Duck", out); + } + + @Test + public void testServletProducerGetWildcards() throws Exception { + String out = template.requestBody("netty-http:http://localhost:{{port}}/users/456/name=g*", null, String.class); + assertEquals("456;Goofy", out); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + // configure to use netty4-http on localhost with the given port + restConfiguration().component("netty-http").host("localhost").port(getPort()).endpointProperty("nettyHttpBinding", "#mybinding"); + + // use the rest DSL to define the rest services + rest("/users/") + .get("{id}/{query}") + .route() + .to("log:query") + .process(new Processor() { + public void process(Exchange exchange) throws Exception { + String id = exchange.getIn().getHeader("id", String.class); + exchange.getOut().setBody(id + ";Goofy"); + } + }).endRest() + .get("{id}/basic") + .route() + .to("log: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"); + } + }).endRest(); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/b1c9132c/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java ---------------------------------------------------------------------- diff --git a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java index 32fd20c..68bb656 100644 --- a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java +++ b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java @@ -263,7 +263,7 @@ public class HttpServerMultiplexChannelHandler extends SimpleChannelInboundHandl * @param consumerPath the consumer path which may use { } tokens * @return number of wildcards, or <tt>0</tt> if no wildcards */ - private int countWildcards(String consumerPath) { + private static int countWildcards(String consumerPath) { int wildcards = 0; // remove starting/ending slashes