You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2020/03/05 15:49:20 UTC

[camel] branch master updated: CAMEL-14645: Wrong rest mapping on camel-undertow

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new 00dc763  CAMEL-14645: Wrong rest mapping on camel-undertow
00dc763 is described below

commit 00dc76335b436a52ae1e6fab385c0f28b5cfa075
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Mar 5 16:40:24 2020 +0100

    CAMEL-14645: Wrong rest mapping on camel-undertow
---
 .../component/undertow/DefaultUndertowHost.java    |  35 +++-
 .../component/undertow/UndertowComponent.java      |  12 +-
 .../camel/component/undertow/UndertowConsumer.java |  15 +-
 .../camel/component/undertow/UndertowEndpoint.java |   4 +
 .../camel/component/undertow/UndertowHost.java     |   4 +-
 .../camel/component/undertow/UndertowProducer.java |   4 +-
 .../undertow/handlers/CamelRootHandler.java        |   2 +
 .../undertow/handlers/NotFoundHandler.java         |   2 +-
 .../undertow/handlers/RestConsumerPath.java        |  55 +++++++
 .../undertow/handlers/RestRootHandler.java         | 181 +++++++++++++++++++++
 .../undertow/UndertowConsumerUnregisterTest.java   |   6 +-
 .../rest/RestUndertowHttpGetOrderingIssueTest.java |  79 +++++++++
 .../undertow/rest/RestUndertowHttpGetTest.java     |   5 +-
 .../rest/RestUndertowHttpGetWildcardsTest.java     |   2 +-
 .../rest/RestUndertowMethodNotAllowedTest.java     |   7 +-
 15 files changed, 383 insertions(+), 30 deletions(-)

diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHost.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHost.java
index 78d66fb..4a938d5 100644
--- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHost.java
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHost.java
@@ -23,6 +23,7 @@ import io.undertow.UndertowOptions;
 import io.undertow.server.HttpHandler;
 import org.apache.camel.component.undertow.handlers.CamelRootHandler;
 import org.apache.camel.component.undertow.handlers.NotFoundHandler;
+import org.apache.camel.component.undertow.handlers.RestRootHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -35,6 +36,7 @@ public class DefaultUndertowHost implements UndertowHost {
     private final UndertowHostKey key;
     private final UndertowHostOptions options;
     private final CamelRootHandler rootHandler;
+    private final RestRootHandler restHandler;
     private Undertow undertow;
     private String hostString;
 
@@ -45,7 +47,9 @@ public class DefaultUndertowHost implements UndertowHost {
     public DefaultUndertowHost(UndertowHostKey key, UndertowHostOptions options) {
         this.key = key;
         this.options = options;
-        rootHandler = new CamelRootHandler(new NotFoundHandler());
+        this.rootHandler = new CamelRootHandler(new NotFoundHandler());
+        this.restHandler = new RestRootHandler();
+        this.restHandler.init(key.getPort());
     }
 
     @Override
@@ -54,7 +58,7 @@ public class DefaultUndertowHost implements UndertowHost {
     }
 
     @Override
-    public synchronized HttpHandler registerHandler(HttpHandlerRegistrationInfo registrationInfo, HttpHandler handler) {
+    public synchronized HttpHandler registerHandler(UndertowConsumer consumer, HttpHandlerRegistrationInfo registrationInfo, HttpHandler handler) {
         if (undertow == null) {
             Undertow.Builder builder = Undertow.builder();
             if (key.getSslContext() != null) {
@@ -81,7 +85,12 @@ public class DefaultUndertowHost implements UndertowHost {
                 }
             }
 
-            undertow = builder.setHandler(rootHandler).build();
+            if (consumer != null && consumer.isRest()) {
+                // use the rest handler as its a rest consumer
+                undertow = builder.setHandler(restHandler).build();
+            } else {
+                undertow = builder.setHandler(rootHandler).build();
+            }
             LOG.info("Starting Undertow server on {}://{}:{}", key.getSslContext() != null ? "https" : "http", key.getHost(), key.getPort());
 
             try {
@@ -102,18 +111,30 @@ public class DefaultUndertowHost implements UndertowHost {
                 throw e;
             }
         }
-        return rootHandler.add(registrationInfo.getUri().getPath(), registrationInfo.getMethodRestrict(), registrationInfo.isMatchOnUriPrefix(), handler);
+        if (consumer != null && consumer.isRest()) {
+            restHandler.addConsumer(consumer);
+            return restHandler;
+        } else {
+            return rootHandler.add(registrationInfo.getUri().getPath(), registrationInfo.getMethodRestrict(), registrationInfo.isMatchOnUriPrefix(), handler);
+        }
     }
 
     @Override
-    public synchronized void unregisterHandler(HttpHandlerRegistrationInfo registrationInfo) {
+    public synchronized void unregisterHandler(UndertowConsumer consumer, HttpHandlerRegistrationInfo registrationInfo) {
         if (undertow == null) {
             return;
         }
 
-        rootHandler.remove(registrationInfo.getUri().getPath(), registrationInfo.getMethodRestrict(), registrationInfo.isMatchOnUriPrefix());
+        boolean stop;
+        if (consumer != null && consumer.isRest()) {
+            restHandler.removeConsumer(consumer);
+            stop = restHandler.consumers() <= 0;
+        } else {
+            rootHandler.remove(registrationInfo.getUri().getPath(), registrationInfo.getMethodRestrict(), registrationInfo.isMatchOnUriPrefix());
+            stop = rootHandler.isEmpty();
+        }
 
-        if (rootHandler.isEmpty()) {
+        if (stop) {
             LOG.info("Stopping Undertow server on {}://{}:{}", key.getSslContext() != null ? "https" : "http", key.getHost(), key.getPort());
             undertow.stop();
             undertow = null;
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 bfd7616..3f963e8 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
@@ -233,6 +233,10 @@ public class UndertowComponent extends DefaultComponent implements RestConsumerF
         if (config.getConsumerProperties() != null && !config.getConsumerProperties().isEmpty()) {
             setProperties(camelContext, consumer, config.getConsumerProperties());
         }
+        if (consumer instanceof UndertowConsumer) {
+            // mark the consumer as a rest consumer
+            ((UndertowConsumer) consumer).setRest(true);
+        }
 
         return consumer;
     }
@@ -307,7 +311,7 @@ public class UndertowComponent extends DefaultComponent implements RestConsumerF
         }
     }
 
-    public HttpHandler registerEndpoint(HttpHandlerRegistrationInfo registrationInfo, SSLContext sslContext, HttpHandler handler) {
+    public HttpHandler registerEndpoint(UndertowConsumer consumer, HttpHandlerRegistrationInfo registrationInfo, SSLContext sslContext, HttpHandler handler) {
         final URI uri = registrationInfo.getUri();
         final UndertowHostKey key = new UndertowHostKey(uri.getHost(), uri.getPort(), sslContext);
         final UndertowHost host = undertowRegistry.computeIfAbsent(key, k -> createUndertowHost(k));
@@ -315,10 +319,10 @@ public class UndertowComponent extends DefaultComponent implements RestConsumerF
         host.validateEndpointURI(uri);
         handlers.add(registrationInfo);
 
-        return host.registerHandler(registrationInfo, handler);
+        return host.registerHandler(consumer, registrationInfo, handler);
     }
 
-    public void unregisterEndpoint(HttpHandlerRegistrationInfo registrationInfo, SSLContext sslContext) {
+    public void unregisterEndpoint(UndertowConsumer consumer, HttpHandlerRegistrationInfo registrationInfo, SSLContext sslContext) {
         final URI uri = registrationInfo.getUri();
         final UndertowHostKey key = new UndertowHostKey(uri.getHost(), uri.getPort(), sslContext);
         final UndertowHost host = undertowRegistry.get(key);
@@ -329,7 +333,7 @@ public class UndertowComponent extends DefaultComponent implements RestConsumerF
         // may not have any instance of UndertowHost associated to the given
         // registrationInfo
         if (host != null) {
-            host.unregisterHandler(registrationInfo);
+            host.unregisterHandler(consumer, registrationInfo);
         }
     }
 
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowConsumer.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowConsumer.java
index 06904a9..b104f7e 100644
--- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowConsumer.java
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowConsumer.java
@@ -62,11 +62,20 @@ public class UndertowConsumer extends DefaultConsumer implements HttpHandler, Su
 
     private static final Logger LOG = LoggerFactory.getLogger(UndertowConsumer.class);
     private CamelWebSocketHandler webSocketHandler;
+    private boolean rest;
 
     public UndertowConsumer(UndertowEndpoint endpoint, Processor processor) {
         super(endpoint, processor);
     }
 
+    public boolean isRest() {
+        return rest;
+    }
+
+    public void setRest(boolean rest) {
+        this.rest = rest;
+    }
+
     @Override
     public UndertowEndpoint getEndpoint() {
         return (UndertowEndpoint) super.getEndpoint();
@@ -81,7 +90,7 @@ public class UndertowConsumer extends DefaultConsumer implements HttpHandler, Su
              * note that the new CamelWebSocketHandler() we pass to registerEndpoint() does not necessarily have to be
              * the same instance that is returned from there
              */
-            this.webSocketHandler = (CamelWebSocketHandler) endpoint.getComponent().registerEndpoint(endpoint.getHttpHandlerRegistrationInfo(), endpoint.getSslContext(), new CamelWebSocketHandler());
+            this.webSocketHandler = (CamelWebSocketHandler) endpoint.getComponent().registerEndpoint(this, endpoint.getHttpHandlerRegistrationInfo(), endpoint.getSslContext(), new CamelWebSocketHandler());
             this.webSocketHandler.setConsumer(this);
         } else {
             // allow for HTTP 1.1 continue
@@ -101,7 +110,7 @@ public class UndertowConsumer extends DefaultConsumer implements HttpHandler, Su
             if (endpoint.getHandlers() != null) {
                 httpHandler = this.wrapHandler(httpHandler, endpoint);
             }
-            endpoint.getComponent().registerEndpoint(endpoint.getHttpHandlerRegistrationInfo(), endpoint.getSslContext(), Handlers.httpContinueRead(
+            endpoint.getComponent().registerEndpoint(this, endpoint.getHttpHandlerRegistrationInfo(), endpoint.getSslContext(), Handlers.httpContinueRead(
                     // wrap with EagerFormParsingHandler to enable undertow form parsers
                     httpHandler));
         }
@@ -114,7 +123,7 @@ public class UndertowConsumer extends DefaultConsumer implements HttpHandler, Su
             this.webSocketHandler.setConsumer(null);
         }
         UndertowEndpoint endpoint = getEndpoint();
-        endpoint.getComponent().unregisterEndpoint(endpoint.getHttpHandlerRegistrationInfo(), endpoint.getSslContext());
+        endpoint.getComponent().unregisterEndpoint(this, endpoint.getHttpHandlerRegistrationInfo(), endpoint.getSslContext());
     }
 
     @Override
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowEndpoint.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowEndpoint.java
index 81a2edc..010af01 100644
--- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowEndpoint.java
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowEndpoint.java
@@ -208,6 +208,10 @@ public class UndertowEndpoint extends DefaultEndpoint implements AsyncEndpoint,
         return matchOnUriPrefix;
     }
 
+    public boolean isMatchOnUriPrefix() {
+        return matchOnUriPrefix != null && matchOnUriPrefix;
+    }
+
     /**
      * Whether or not the consumer should try to find a target consumer by matching the URI prefix if no exact match is found.
      */
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHost.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHost.java
index 74be127..a8c008e 100644
--- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHost.java
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHost.java
@@ -46,7 +46,7 @@ public interface UndertowHost {
      * @return the given {@code handler} or a different {@link HttpHandler} that has been registered with the given
      *         {@link HttpHandlerRegistrationInfo} earlier.
      */
-    HttpHandler registerHandler(HttpHandlerRegistrationInfo registrationInfo, HttpHandler handler);
+    HttpHandler registerHandler(UndertowConsumer consumer, HttpHandlerRegistrationInfo registrationInfo, HttpHandler handler);
 
     /**
      * Unregister a handler with the given {@link HttpHandlerRegistrationInfo}. Note that if
@@ -54,6 +54,6 @@ public interface UndertowHost {
      * equivalent {@link HttpHandlerRegistrationInfo} then {@link #unregisterHandler(HttpHandlerRegistrationInfo)} must
      * be called the same number of times to unregister the associated handler completely.
      */
-    void unregisterHandler(HttpHandlerRegistrationInfo registrationInfo);
+    void unregisterHandler(UndertowConsumer consumer, HttpHandlerRegistrationInfo registrationInfo);
 
 }
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowProducer.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowProducer.java
index 0278894..f7c5862 100644
--- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowProducer.java
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowProducer.java
@@ -248,7 +248,7 @@ public class UndertowProducer extends DefaultAsyncProducer {
         client = UndertowClient.getInstance();
 
         if (endpoint.isWebSocket()) {
-            this.webSocketHandler = (CamelWebSocketHandler) endpoint.getComponent().registerEndpoint(endpoint.getHttpHandlerRegistrationInfo(), endpoint.getSslContext(), new CamelWebSocketHandler());
+            this.webSocketHandler = (CamelWebSocketHandler) endpoint.getComponent().registerEndpoint(null, endpoint.getHttpHandlerRegistrationInfo(), endpoint.getSslContext(), new CamelWebSocketHandler());
         }
 
         LOG.debug("Created worker: {} with options: {}", worker, options);
@@ -259,7 +259,7 @@ public class UndertowProducer extends DefaultAsyncProducer {
         super.doStop();
 
         if (endpoint.isWebSocket()) {
-            endpoint.getComponent().unregisterEndpoint(endpoint.getHttpHandlerRegistrationInfo(), endpoint.getSslContext());
+            endpoint.getComponent().unregisterEndpoint(null, endpoint.getHttpHandlerRegistrationInfo(), endpoint.getSslContext());
         }
 
         if (worker != null && !worker.isShutdown()) {
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/CamelRootHandler.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/CamelRootHandler.java
index 159ad67..05965ac 100644
--- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/CamelRootHandler.java
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/CamelRootHandler.java
@@ -23,6 +23,8 @@ import io.undertow.util.URLUtils;
 
 /**
  * Custom root handler to enable hot swapping individual handlers assigned for each path template and/or HTTP method.
+ *
+ * @see RestRootHandler
  */
 public class CamelRootHandler implements HttpHandler {
     private CamelPathHandler pathHandler;
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/NotFoundHandler.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/NotFoundHandler.java
index 3e82c48..ddcd415 100644
--- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/NotFoundHandler.java
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/NotFoundHandler.java
@@ -27,7 +27,7 @@ public class NotFoundHandler implements HttpHandler {
 
     @Override
     public void handleRequest(HttpServerExchange exchange) throws Exception {
-        exchange.setResponseCode(404);
+        exchange.setStatusCode(404);
         exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
         exchange.getResponseSender().send("No matching path found");
     }
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/RestConsumerPath.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/RestConsumerPath.java
new file mode 100644
index 0000000..a12802b
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/RestConsumerPath.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.undertow.handlers;
+
+import org.apache.camel.component.undertow.UndertowConsumer;
+import org.apache.camel.support.RestConsumerContextPathMatcher;
+
+public class RestConsumerPath implements RestConsumerContextPathMatcher.ConsumerPath<UndertowConsumer> {
+
+    private final UndertowConsumer consumer;
+
+    public RestConsumerPath(UndertowConsumer consumer) {
+        this.consumer = consumer;
+    }
+
+    @Override
+    public String getRestrictMethod() {
+        return consumer.getEndpoint().getHttpMethodRestrict();
+    }
+
+    @Override
+    public String getConsumerPath() {
+        return consumer.getEndpoint().getHttpURI().getPath();
+    }
+
+    @Override
+    public UndertowConsumer getConsumer() {
+        return consumer;
+    }
+
+    @Override
+    public boolean isMatchOnUriPrefix() {
+        return consumer.getEndpoint().isMatchOnUriPrefix();
+    }
+
+    @Override
+    public String toString() {
+        return getConsumerPath();
+    }
+
+}
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/RestRootHandler.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/RestRootHandler.java
new file mode 100644
index 0000000..2e45a1a
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/RestRootHandler.java
@@ -0,0 +1,181 @@
+/*
+ * 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.handlers;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.stream.Collectors;
+
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.util.Headers;
+import org.apache.camel.component.undertow.UndertowConsumer;
+import org.apache.camel.support.RestConsumerContextPathMatcher;
+import org.apache.camel.util.UnsafeUriCharactersEncoder;
+
+/**
+ * Root handler for Camel rest-dsl.
+ *
+ * @see CamelRootHandler
+ */
+public class RestRootHandler implements HttpHandler {
+
+    private static final List<String> METHODS = Arrays.asList("GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "OPTIONS", "CONNECT", "PATCH");
+
+    private final Set<UndertowConsumer> consumers = new CopyOnWriteArraySet<>();
+
+    private int port;
+    private String token;
+    private int len;
+
+    /**
+     * Initializes this handler with the given port.
+     */
+    public void init(int port) {
+        this.port = port;
+        this.token = ":" + port;
+        this.len = token.length();
+    }
+
+    /**
+     * Adds the given consumer.
+     */
+    public void addConsumer(UndertowConsumer consumer) {
+        consumers.add(consumer);
+    }
+
+    /**
+     * Removes the given consumer
+     */
+    public void removeConsumer(UndertowConsumer consumer) {
+        consumers.remove(consumer);
+    }
+
+    /**
+     * Number of active consumers
+     */
+    public int consumers() {
+        return consumers.size();
+    }
+
+    @Override
+    public void handleRequest(HttpServerExchange httpServerExchange) throws Exception {
+        String method = httpServerExchange.getRequestMethod().toString();
+
+        HttpHandler handler = getHandler(httpServerExchange, method);
+        if (handler != null) {
+            handler.handleRequest(httpServerExchange);
+        } else {
+            // okay we cannot process this requires so return either 404 or 405.
+            // to know if its 405 then we need to check if any other HTTP method would have a consumer for the "same" request
+            boolean hasAnyMethod = METHODS.stream().anyMatch(m -> isHttpMethodAllowed(httpServerExchange, m));
+            if (hasAnyMethod) {
+                //method match error, return 405
+                httpServerExchange.setStatusCode(405);
+                httpServerExchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
+                httpServerExchange.getResponseSender().send("Method not allowed");
+            } else {
+                // this resource is not found, return 404
+                httpServerExchange.setStatusCode(404);
+                httpServerExchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
+                httpServerExchange.getResponseSender().send("No matching path found");
+            }
+        }
+    }
+
+    private HttpHandler getHandler(HttpServerExchange httpServerExchange, String method) {
+        HttpHandler answer = null;
+
+        // need to strip out host and port etc, as we only need the context-path for matching
+        if (method == null) {
+            return null;
+        }
+
+        String path = httpServerExchange.getRequestURI();
+        int idx = path.indexOf(token);
+        if (idx > -1) {
+            path = path.substring(idx + len);
+        }
+        // use the path as key to find the consumer handler to use
+        path = pathAsKey(path);
+
+        List<RestConsumerContextPathMatcher.ConsumerPath> paths = new ArrayList<>();
+        for (final UndertowConsumer consumer : consumers) {
+            paths.add(new RestConsumerPath(consumer));
+        }
+
+        RestConsumerContextPathMatcher.ConsumerPath<UndertowConsumer> best = RestConsumerContextPathMatcher.matchBestPath(method, path, paths);
+        if (best != null) {
+            answer = best.getConsumer();
+        }
+
+        // fallback to regular matching
+        List<UndertowConsumer> candidates = new ArrayList<>();
+        if (answer == null) {
+            for (final UndertowConsumer consumer : consumers) {
+
+                String consumerPath = consumer.getEndpoint().getHttpURI().getPath();
+                boolean matchOnUriPrefix = consumer.getEndpoint().isMatchOnUriPrefix();
+                // Just make sure the we get the right consumer path first
+                if (RestConsumerContextPathMatcher.matchPath(path, consumerPath, matchOnUriPrefix)) {
+                    candidates.add(consumer);
+                }
+            }
+        }
+
+        // extra filter by restrict
+        candidates = candidates.stream().filter(c -> matchRestMethod(method, c.getEndpoint().getHttpMethodRestrict())).collect(Collectors.toList());
+        if (candidates.size() == 1) {
+            answer = candidates.get(0);
+        }
+
+        return answer;
+    }
+
+    private static String pathAsKey(String path) {
+        // cater for default path
+        if (path == null || path.equals("/")) {
+            path = "";
+        }
+
+        // strip out query parameters
+        int idx = path.indexOf('?');
+        if (idx > -1) {
+            path = path.substring(0, idx);
+        }
+
+        // strip of ending /
+        if (path.endsWith("/")) {
+            path = path.substring(0, path.length() - 1);
+        }
+
+        return UnsafeUriCharactersEncoder.encodeHttpURI(path);
+    }
+
+    private static boolean matchRestMethod(String method, String restrict) {
+        return restrict == null || restrict.toLowerCase(Locale.ENGLISH).contains(method.toLowerCase(Locale.ENGLISH));
+    }
+
+    private boolean isHttpMethodAllowed(HttpServerExchange httpServerExchange, String method) {
+        return getHandler(httpServerExchange, method) != null;
+    }
+
+}
diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowConsumerUnregisterTest.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowConsumerUnregisterTest.java
index cf1c46c..10e6a2c 100644
--- a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowConsumerUnregisterTest.java
+++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/UndertowConsumerUnregisterTest.java
@@ -34,8 +34,8 @@ public class UndertowConsumerUnregisterTest extends BaseUndertowTest {
         UndertowConsumer consumerFoo = (UndertowConsumer) context.getRoute("route-foo").getConsumer();
         UndertowConsumer consumerBar = (UndertowConsumer) context.getRoute("route-bar").getConsumer();
 
-        component.unregisterEndpoint(consumerFoo.getEndpoint().getHttpHandlerRegistrationInfo(), consumerFoo.getEndpoint().getSslContext());
-        component.unregisterEndpoint(consumerBar.getEndpoint().getHttpHandlerRegistrationInfo(), consumerBar.getEndpoint().getSslContext());
+        component.unregisterEndpoint(consumerFoo, consumerFoo.getEndpoint().getHttpHandlerRegistrationInfo(), consumerFoo.getEndpoint().getSslContext());
+        component.unregisterEndpoint(consumerBar, consumerBar.getEndpoint().getHttpHandlerRegistrationInfo(), consumerBar.getEndpoint().getSslContext());
 
         try {
             template.requestBody("undertow:http://localhost:{{port}}/foo", null, String.class);
@@ -68,7 +68,7 @@ public class UndertowConsumerUnregisterTest extends BaseUndertowTest {
 
         UndertowComponent component = context.getComponent("undertow", UndertowComponent.class);
         UndertowConsumer consumerFoo = (UndertowConsumer) context.getRoute("route-foo").getConsumer();
-        component.unregisterEndpoint(consumerFoo.getEndpoint().getHttpHandlerRegistrationInfo(), consumerFoo.getEndpoint().getSslContext());
+        component.unregisterEndpoint(consumerFoo, consumerFoo.getEndpoint().getHttpHandlerRegistrationInfo(), consumerFoo.getEndpoint().getSslContext());
 
         ret = template.request("undertow:http://localhost:{{port}}/foo", sender);
         Assert.assertEquals(404, ret.getMessage().getHeader(Exchange.HTTP_RESPONSE_CODE));
diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpGetOrderingIssueTest.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpGetOrderingIssueTest.java
new file mode 100644
index 0000000..9f1f916
--- /dev/null
+++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpGetOrderingIssueTest.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.undertow.rest;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.undertow.BaseUndertowTest;
+import org.junit.Test;
+
+public class RestUndertowHttpGetOrderingIssueTest extends BaseUndertowTest {
+    
+    @Test
+    public void testProducerGet() throws Exception {
+        getMockEndpoint("mock:root").expectedMessageCount(1);
+        String out = template.requestBody("undertow:http://localhost:{{port}}", null, String.class);
+        assertEquals("Route without name", out);
+        assertMockEndpointsSatisfied();
+
+        resetMocks();
+
+        getMockEndpoint("mock:pippo").expectedMessageCount(1);
+        out = template.requestBody("undertow:http://localhost:{{port}}/Donald", null, String.class);
+        assertEquals("Route with name: Donald", out);
+        assertMockEndpointsSatisfied();
+
+        resetMocks();
+
+        getMockEndpoint("mock:bar").expectedMessageCount(1);
+        out = template.requestBody("undertow:http://localhost:{{port}}/bar", null, String.class);
+        assertEquals("Going to the bar", out);
+        assertMockEndpointsSatisfied();
+    }
+
+    @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());
+
+                rest()
+                    .get("/bar")
+                        .route()
+                        .setBody().constant("Going to the bar")
+                        .to("mock:bar")
+                        .setHeader("Content-Type", constant("text/plain"));
+
+                rest()
+                    .get("/{pippo}")
+                        .route()
+                        .setBody().simple("Route with name: ${header.pippo}")
+                        .to("mock:pippo")
+                        .setHeader("Content-Type", constant("text/plain"));
+
+                rest()
+                    .get("/")
+                        .route()
+                        .setBody().constant("Route without name")
+                        .to("mock:root")
+                        .setHeader("Content-Type", constant("text/plain"));
+            }
+        };
+    }
+
+}
diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpGetTest.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpGetTest.java
index 40820a4..061b286 100644
--- a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpGetTest.java
+++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpGetTest.java
@@ -25,9 +25,6 @@ import org.junit.Test;
 
 public class RestUndertowHttpGetTest extends BaseUndertowTest {
     
-    @BindToRegistry("mybinding")
-    private UndertowHttpBinding binding = new DefaultUndertowHttpBinding();
-    
     @Test
     public void testProducerGet() throws Exception {
         String out = template.requestBody("undertow:http://localhost:{{port}}/users/123/basic", null, String.class);
@@ -40,7 +37,7 @@ public class RestUndertowHttpGetTest extends BaseUndertowTest {
             @Override
             public void configure() throws Exception {
                 // configure to use undertow on localhost with the given port
-                restConfiguration().component("undertow").host("localhost").port(getPort()).endpointProperty("undertowHttpBinding", "#mybinding");
+                restConfiguration().component("undertow").host("localhost").port(getPort());
 
                 // use the rest DSL to define the rest services
                 rest("/users/")
diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpGetWildcardsTest.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpGetWildcardsTest.java
index d2b2571..9fba51b 100644
--- a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpGetWildcardsTest.java
+++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpGetWildcardsTest.java
@@ -46,7 +46,7 @@ public class RestUndertowHttpGetWildcardsTest extends BaseUndertowTest {
             @Override
             public void configure() throws Exception {
                 // configure to use undertow on localhost with the given port
-                restConfiguration().component("undertow").host("localhost").port(getPort()).endpointProperty("undertowHttpBinding", "#mybinding");
+                restConfiguration().component("undertow").host("localhost").port(getPort());
 
                 // use the rest DSL to define the rest services
                 rest("/users/").get("{id}/{query}").route().to("log:query").process(exchange -> {
diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowMethodNotAllowedTest.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowMethodNotAllowedTest.java
index e66329d..5905340 100644
--- a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowMethodNotAllowedTest.java
+++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowMethodNotAllowedTest.java
@@ -23,10 +23,11 @@ import org.apache.camel.http.common.HttpOperationFailedException;
 import org.junit.Test;
 
 public class RestUndertowMethodNotAllowedTest extends BaseUndertowTest {
+
     @Test
-    public void testMethodNotAllowed() {
+    public void testPostMethodNotAllowed() {
         try {
-            template.sendBody("http://localhost:" + getPort() + "/users/123/basic", "body");
+            template.sendBodyAndHeader("http://localhost:" + getPort() + "/users/123/basic", "body", Exchange.HTTP_METHOD, "POST");
             fail("Shall not pass!");
         } catch (Exception e) {
             HttpOperationFailedException hofe = assertIsInstanceOf(HttpOperationFailedException.class, e.getCause());
@@ -35,7 +36,7 @@ public class RestUndertowMethodNotAllowedTest extends BaseUndertowTest {
     }
     
     @Test
-    public void testMethodAllowed() {
+    public void testGetMethodAllowed() {
         try {
             template.sendBodyAndHeader("http://localhost:" + getPort() + "/users/123/basic", "body", Exchange.HTTP_METHOD, "GET");
         } catch (Exception e) {