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) {