Repository: camel Updated Branches: refs/heads/master cba6e2e8f -> 61a1a2ab0
CAMEL-7354: Rest DSL. Integrate with camel-jetty. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/c5098c1d Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/c5098c1d Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/c5098c1d Branch: refs/heads/master Commit: c5098c1df62e54ca7e7b5482f2f609ff7181e81f Parents: cba6e2e Author: Claus Ibsen <davscl...@apache.org> Authored: Mon Jul 28 13:49:07 2014 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Mon Jul 28 13:49:07 2014 +0200 ---------------------------------------------------------------------- .../component/jetty/JettyRestHttpBinding.java | 36 +++++---- ...JettyRestServletResolveConsumerStrategy.java | 78 ++++++++++---------- .../jetty/rest/RestPathMatchingTest.java | 55 ++++++++++++++ 3 files changed, 117 insertions(+), 52 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/c5098c1d/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestHttpBinding.java ---------------------------------------------------------------------- diff --git a/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestHttpBinding.java b/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestHttpBinding.java index b92cf3f..178d5a1 100644 --- a/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestHttpBinding.java +++ b/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestHttpBinding.java @@ -23,8 +23,6 @@ import org.apache.camel.component.http.HttpMessage; public class JettyRestHttpBinding extends DefaultHttpBinding { - // TODO: a better and faster rest pattern matcher, without the .split as they may be slower - @Override protected void populateRequestParameters(HttpServletRequest request, HttpMessage message) throws Exception { super.populateRequestParameters(request, message); @@ -40,21 +38,31 @@ public class JettyRestHttpBinding extends DefaultHttpBinding { JettyHttpEndpoint endpoint = (JettyHttpEndpoint) message.getExchange().getFromEndpoint(); String consumerPath = endpoint.getPath(); - String[] paths = path.split("/"); - String[] consumerPaths = consumerPath.split("/"); + if (useRestMatching(consumerPath)) { - for (int i = 0; i < consumerPaths.length; i++) { - if (paths.length < i) { - break; - } - String p1 = consumerPaths[i]; - if (p1.startsWith("{") && p1.endsWith("}")) { - String key = p1.substring(1, p1.length() - 1); - String value = paths[i]; - if (value != null) { - message.setHeader(key, value); + // split using single char / is optimized in the jdk + String[] paths = path.split("/"); + String[] consumerPaths = consumerPath.split("/"); + + for (int i = 0; i < consumerPaths.length; i++) { + if (paths.length < i) { + break; + } + String p1 = consumerPaths[i]; + if (p1.startsWith("{") && p1.endsWith("}")) { + String key = p1.substring(1, p1.length() - 1); + String value = paths[i]; + if (value != null) { + message.setHeader(key, value); + } } } } } + + private boolean useRestMatching(String path) { + // only need to do rest matching if using { } placeholders + return path.indexOf('{') > -1; + } + } http://git-wip-us.apache.org/repos/asf/camel/blob/c5098c1d/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestServletResolveConsumerStrategy.java ---------------------------------------------------------------------- diff --git a/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestServletResolveConsumerStrategy.java b/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestServletResolveConsumerStrategy.java index 4832f84..34f8ce2 100644 --- a/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestServletResolveConsumerStrategy.java +++ b/components/camel-jetty/src/main/java/org/apache/camel/component/jetty/JettyRestServletResolveConsumerStrategy.java @@ -28,37 +28,56 @@ import org.apache.camel.util.ObjectHelper; */ public class JettyRestServletResolveConsumerStrategy extends HttpServletResolveConsumerStrategy { - // TODO: a better and faster rest pattern matcher, without the .split as they may be slower - @Override public HttpConsumer resolve(HttpServletRequest request, Map<String, HttpConsumer> consumers) { - HttpConsumer answer = super.resolve(request, consumers); - - if (answer == null) { - - String path = request.getPathInfo(); - if (path == null) { - return null; - } + String path = request.getPathInfo(); + if (path == null) { + return null; + } - for (String key : consumers.keySet()) { - String consumerPath = normalizePath(key); - String requestPath = normalizePath(path); - if (matchPaths(requestPath, consumerPath)) { - answer = consumers.get(key); - break; - } + for (String key : consumers.keySet()) { + if (useRestMatching(key) && matchRestPath(path, key)) { + return consumers.get(key); } } - return answer; + // fallback to default + return super.resolve(request, consumers); } - private boolean matchPaths(String requestPath, String consumerPath) { + private boolean useRestMatching(String path) { + // only need to do rest matching if using { } placeholders + return path.indexOf('{') > -1; + } + + /** + * Matches the given request path with the configured consumer path + * + * @param requestPath the request path + * @param consumerPath the consumer path which may use { } tokens + * @return <tt>true</tt> if matched, <tt>false</tt> otherwise + */ + public boolean matchRestPath(String requestPath, String consumerPath) { + // remove starting/ending slashes + if (requestPath.startsWith("/")) { + requestPath = requestPath.substring(1); + } + if (requestPath.endsWith("/")) { + requestPath = requestPath.substring(0, requestPath.length() - 1); + } + // remove starting/ending slashes + if (consumerPath.startsWith("/")) { + consumerPath = consumerPath.substring(1); + } + if (consumerPath.endsWith("/")) { + consumerPath = consumerPath.substring(0, consumerPath.length() - 1); + } + + // split using single char / is optimized in the jdk String[] requestPaths = requestPath.split("/"); String[] consumerPaths = consumerPath.split("/"); - // must be same length + // must be same number of path's if (requestPaths.length != consumerPaths.length) { return false; } @@ -67,7 +86,7 @@ public class JettyRestServletResolveConsumerStrategy extends HttpServletResolveC String p1 = requestPaths[i]; String p2 = consumerPaths[i]; - if (p2.equals("*")) { + if (p2.startsWith("{") && p2.endsWith("}")) { // always matches continue; } @@ -81,21 +100,4 @@ public class JettyRestServletResolveConsumerStrategy extends HttpServletResolveC return true; } - protected String normalizePath(String path) { - StringBuilder sb = new StringBuilder(); - String[] paths = path.split("/"); - for (String s : paths) { - if (ObjectHelper.isEmpty(s)) { - continue; - } - sb.append("/"); - if (s.startsWith("{") && s.endsWith("}")) { - sb.append("*"); - } else { - sb.append(s); - } - } - return sb.toString(); - } - } http://git-wip-us.apache.org/repos/asf/camel/blob/c5098c1d/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestPathMatchingTest.java ---------------------------------------------------------------------- diff --git a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestPathMatchingTest.java b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestPathMatchingTest.java new file mode 100644 index 0000000..df66449 --- /dev/null +++ b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestPathMatchingTest.java @@ -0,0 +1,55 @@ +/** + * 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.jetty.rest; + +import junit.framework.TestCase; +import org.apache.camel.component.jetty.JettyRestServletResolveConsumerStrategy; + +public class RestPathMatchingTest extends TestCase { + + private JettyRestServletResolveConsumerStrategy matcher = new JettyRestServletResolveConsumerStrategy(); + + public void testRestPathMatcher() throws Exception { + assertTrue(matcher.matchRestPath("/foo/", "/foo/")); + assertTrue(matcher.matchRestPath("/foo/", "foo/")); + assertTrue(matcher.matchRestPath("/foo/", "foo")); + assertTrue(matcher.matchRestPath("foo/", "foo")); + assertTrue(matcher.matchRestPath("foo", "foo")); + assertTrue(matcher.matchRestPath("foo/", "foo")); + assertTrue(matcher.matchRestPath("/foo/", "foo")); + + assertTrue(matcher.matchRestPath("/foo/1234/list/2014", "/foo/1234/list/2014")); + assertTrue(matcher.matchRestPath("/foo/1234/list/2014/", "/foo/1234/list/2014")); + assertTrue(matcher.matchRestPath("/foo/1234/list/2014", "/foo/1234/list/2014/")); + assertTrue(matcher.matchRestPath("/foo/1234/list/2014/", "/foo/1234/list/2014/")); + assertTrue(matcher.matchRestPath("/foo/1234/list/2014", "/foo/{user}/list/{year}")); + + assertFalse(matcher.matchRestPath("/foo/", "/bar/")); + assertFalse(matcher.matchRestPath("/foo/1234/list/2014", "/foo/1234/list/2015")); + assertFalse(matcher.matchRestPath("/foo/1234/list/2014/", "/foo/1234/list/2015")); + assertFalse(matcher.matchRestPath("/foo/1234/list/2014", "/foo/1234/list/2015/")); + assertFalse(matcher.matchRestPath("/foo/1234/list/2014/", "/foo/1234/list/2015/")); + assertFalse(matcher.matchRestPath("/foo/1234/list/2014", "/foo/{user}/list/")); + + assertTrue(matcher.matchRestPath("/foo/1/list/2", "/foo/{user}/list/{year}")); + assertTrue(matcher.matchRestPath("/foo/1234567890/list/2", "/foo/{user}/list/{year}")); + assertTrue(matcher.matchRestPath("/foo/1234567890/list/1234567890", "/foo/{user}/list/{year}")); + + assertTrue(matcher.matchRestPath("/123/list/2014", "/{user}/list/{year}")); + assertTrue(matcher.matchRestPath("/1234567890/list/2014", "/{user}/list/{year}")); + } +}