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
commit c3cd89585c4a437767a8e72aee388f3ed17c62e9 Author: Claus Ibsen <[email protected]> AuthorDate: Mon Aug 27 14:58:57 2018 +0200 CAMEL-12753: Fixed camel-undertow consumer with OPTIONS in rest-dsl to return mutiple verbs if the same context-path has more http verbs like GET,POST etc. Thanks to Tomas Turek for unit test --- .../undertow/HttpHandlerRegistrationInfo.java | 20 +++++++++++++ .../component/undertow/UndertowComponent.java | 13 +++++++-- .../camel/component/undertow/UndertowConsumer.java | 33 ++++++++++++++++++---- .../undertow/rest/RestUndertowHttpOptionsTest.java | 19 ++++++++++++- 4 files changed, 75 insertions(+), 10 deletions(-) diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/HttpHandlerRegistrationInfo.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/HttpHandlerRegistrationInfo.java index ce93093..9e55856 100644 --- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/HttpHandlerRegistrationInfo.java +++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/HttpHandlerRegistrationInfo.java @@ -17,6 +17,7 @@ package org.apache.camel.component.undertow; import java.net.URI; +import java.util.Objects; public class HttpHandlerRegistrationInfo { @@ -48,4 +49,23 @@ public class HttpHandlerRegistrationInfo { return uri + "?matchOnUriPrefix=" + matchOnUriPrefix + "&methodRestrict=" + methodRestrict; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + HttpHandlerRegistrationInfo that = (HttpHandlerRegistrationInfo) o; + return Objects.equals(matchOnUriPrefix, that.matchOnUriPrefix) + && Objects.equals(methodRestrict, that.methodRestrict) + && Objects.equals(uri, that.uri); + } + + @Override + public int hashCode() { + return Objects.hash(matchOnUriPrefix, methodRestrict, uri); + } + } 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 62014cd..4857b59 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 @@ -19,14 +19,14 @@ package org.apache.camel.component.undertow; import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; +import java.util.HashSet; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; - import javax.net.ssl.SSLContext; import io.undertow.server.HttpHandler; - import org.apache.camel.CamelContext; import org.apache.camel.ComponentVerifier; import org.apache.camel.Consumer; @@ -61,7 +61,8 @@ import org.slf4j.LoggerFactory; public class UndertowComponent extends DefaultComponent implements RestConsumerFactory, RestApiConsumerFactory, RestProducerFactory, VerifiableComponent, SSLContextParametersAware { private static final Logger LOG = LoggerFactory.getLogger(UndertowEndpoint.class); - private Map<UndertowHostKey, UndertowHost> undertowRegistry = new ConcurrentHashMap<>(); + private final Map<UndertowHostKey, UndertowHost> undertowRegistry = new ConcurrentHashMap<>(); + private final Set<HttpHandlerRegistrationInfo> handlers = new HashSet<>(); @Metadata(label = "advanced") private UndertowHttpBinding undertowHttpBinding; @@ -332,6 +333,7 @@ public class UndertowComponent extends DefaultComponent implements RestConsumerF final UndertowHost host = undertowRegistry.computeIfAbsent(key, k -> createUndertowHost(k)); host.validateEndpointURI(uri); + handlers.add(registrationInfo); return host.registerHandler(registrationInfo, handler); } @@ -339,6 +341,7 @@ public class UndertowComponent extends DefaultComponent implements RestConsumerF final URI uri = registrationInfo.getUri(); final UndertowHostKey key = new UndertowHostKey(uri.getHost(), uri.getPort(), sslContext); final UndertowHost host = undertowRegistry.get(key); + handlers.remove(registrationInfo); host.unregisterHandler(registrationInfo); } @@ -400,4 +403,8 @@ public class UndertowComponent extends DefaultComponent implements RestConsumerF protected String getComponentName() { return "undertow"; } + + public Set<HttpHandlerRegistrationInfo> getHandlers() { + return handlers; + } } 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 8abc793..4922d24 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 @@ -17,7 +17,9 @@ package org.apache.camel.component.undertow; import java.io.IOException; +import java.net.URI; import java.nio.ByteBuffer; +import java.util.Collection; import io.undertow.Handlers; import io.undertow.server.HttpHandler; @@ -31,6 +33,7 @@ import io.undertow.util.StatusCodes; import io.undertow.websockets.core.WebSocketChannel; import org.apache.camel.AsyncCallback; +import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.Processor; @@ -38,6 +41,9 @@ import org.apache.camel.TypeConverter; import org.apache.camel.component.undertow.UndertowConstants.EventType; import org.apache.camel.component.undertow.handlers.CamelWebSocketHandler; import org.apache.camel.impl.DefaultConsumer; +import org.apache.camel.util.CollectionStringBuffer; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.StringHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -92,15 +98,30 @@ public class UndertowConsumer extends DefaultConsumer implements HttpHandler { HttpString requestMethod = httpExchange.getRequestMethod(); if (Methods.OPTIONS.equals(requestMethod) && !getEndpoint().isOptionsEnabled()) { - String allowedMethods; - if (getEndpoint().getHttpMethodRestrict() != null) { - allowedMethods = getEndpoint().getHttpMethodRestrict(); - if (!allowedMethods.contains("OPTIONS")) { - allowedMethods = "OPTIONS," + allowedMethods; + CollectionStringBuffer csb = new CollectionStringBuffer(","); + + Collection<HttpHandlerRegistrationInfo> handlers = getEndpoint().getComponent().getHandlers(); + for (HttpHandlerRegistrationInfo reg : handlers) { + URI uri = reg.getUri(); + // what other HTTP methods may exists for the same path + if (reg.getMethodRestrict() != null && getEndpoint().getHttpURI().equals(uri)) { + String restrict = reg.getMethodRestrict(); + if (restrict.endsWith(",OPTIONS")) { + restrict = restrict.substring(0, restrict.length() - 8); + } + csb.append(restrict); } - } else { + } + String allowedMethods = csb.toString(); + if (ObjectHelper.isEmpty(allowedMethods)) { + allowedMethods = getEndpoint().getHttpMethodRestrict(); + } + if (ObjectHelper.isEmpty(allowedMethods)) { allowedMethods = "GET,HEAD,POST,PUT,DELETE,TRACE,OPTIONS,CONNECT,PATCH"; } + if (!allowedMethods.contains("OPTIONS")) { + allowedMethods = allowedMethods + ",OPTIONS"; + } //return list of allowed methods in response headers httpExchange.setStatusCode(StatusCodes.OK); httpExchange.getResponseHeaders().put(ExchangeHeaders.CONTENT_LENGTH, 0); diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpOptionsTest.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpOptionsTest.java index ebd7ce8..afbb6b2 100644 --- a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpOptionsTest.java +++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpOptionsTest.java @@ -43,6 +43,19 @@ public class RestUndertowHttpOptionsTest extends BaseUndertowTest { assertEquals("", exchange.getIn().getBody(String.class)); } + @Test + public void testMultipleHttpOptions() { + Exchange exchange = template.request("undertow:http://localhost:" + getPort() + "/users/v1/options", new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setHeader(Exchange.HTTP_METHOD, "OPTIONS"); + } + }); + assertEquals(200, exchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE)); + assertEquals("GET,POST,OPTIONS", exchange.getOut().getHeader("ALLOW")); + assertEquals("", exchange.getOut().getBody(String.class)); + } + @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @@ -56,7 +69,11 @@ public class RestUndertowHttpOptionsTest extends BaseUndertowTest { .get("v1/customers") .to("mock:customers") .put("v1/{id}") - .to("mock:id"); + .to("mock:id") + .get("v1/options") + .to("mock:options") + .post("v1/options") + .to("mock:options"); } }; }
