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 2015/07/15 11:36:41 UTC

[2/6] camel git commit: Initial commit of Camel Undertow component

Initial commit of Camel Undertow component


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/100b2f40
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/100b2f40
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/100b2f40

Branch: refs/heads/master
Commit: 100b2f408d9169e90b222c039e32021fa4638a1a
Parents: f5ab9e4
Author: David Simansky <ds...@redhat.com>
Authored: Tue Jul 14 17:46:35 2015 +0200
Committer: David Simansky <ds...@redhat.com>
Committed: Wed Jul 15 10:56:18 2015 +0200

----------------------------------------------------------------------
 components/camel-undertow/pom.xml               |  70 ++++
 .../undertow/DefaultUndertowHttpBinding.java    | 359 +++++++++++++++++++
 .../component/undertow/ExchangeHeaders.java     | 176 +++++++++
 .../component/undertow/UndertowComponent.java   | 281 +++++++++++++++
 .../component/undertow/UndertowConsumer.java    |  58 +++
 .../component/undertow/UndertowEndpoint.java    | 196 ++++++++++
 .../component/undertow/UndertowHttpBinding.java |  50 +++
 .../component/undertow/UndertowProducer.java    | 159 ++++++++
 .../component/undertow/UndertowRegistry.java    | 116 ++++++
 .../camel/component/undertow/UndertowUtils.java |  49 +++
 .../undertow/handlers/HttpCamelHandler.java     | 132 +++++++
 .../undertow/handlers/NotFoundHandler.java      |  36 ++
 .../src/main/resources/META-INF/LICENSE.txt     | 203 +++++++++++
 .../src/main/resources/META-INF/NOTICE.txt      |  11 +
 .../org/apache/camel/component/undertow         |   1 +
 .../undertow/UndertowComponentTest.java         |  84 +++++
 .../undertow/UndertowError500Test.java          |  57 +++
 .../component/undertow/UndertowHeaderTest.java  |  57 +++
 .../undertow/UndertowHttpProducerTest.java      |  72 ++++
 .../undertow/UndertowHttpsSpringTest.java       |  72 ++++
 .../undertow/UndertowMethodRestricTest.java     |  78 ++++
 .../undertow/UndertowPrefixMatchingTest.java    |  76 ++++
 .../undertow/UndertowProducerTest.java          |  77 ++++
 .../undertow/UndertowSharedPortTest.java        |  23 ++
 .../src/test/resources/SpringTest.xml           |  48 +++
 .../src/test/resources/ssl/keystore.jks         | Bin 0 -> 2246 bytes
 components/pom.xml                              |   1 +
 27 files changed, 2542 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/100b2f40/components/camel-undertow/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-undertow/pom.xml b/components/camel-undertow/pom.xml
new file mode 100644
index 0000000..bb4b69a
--- /dev/null
+++ b/components/camel-undertow/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~
+  ~ 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.
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>components</artifactId>
+        <version>2.16-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>camel-undertow</artifactId>
+    <packaging>bundle</packaging>
+    <name>Camel :: Undertow</name>
+
+    <properties>
+        <camel.osgi.export.pkg>org.apache.camel.component.undertow.*</camel.osgi.export.pkg>
+        <camel.osgi.export.service>org.apache.camel.spi.ComponentResolver;component=undertow</camel.osgi.export.service>
+        <undertow-version>1.2.8.Final</undertow-version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-http</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.undertow</groupId>
+            <artifactId>undertow-core</artifactId>
+            <version>${undertow-version}</version>
+        </dependency>
+
+        <!-- testing -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-spring</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/100b2f40/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHttpBinding.java
----------------------------------------------------------------------
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHttpBinding.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHttpBinding.java
new file mode 100644
index 0000000..6ef3ba0
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHttpBinding.java
@@ -0,0 +1,359 @@
+/**
+ * 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;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+
+import io.undertow.client.ClientExchange;
+import io.undertow.client.ClientRequest;
+import io.undertow.client.ClientResponse;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.util.Headers;
+import io.undertow.util.HttpString;
+import io.undertow.util.Methods;
+import io.undertow.util.MimeMappings;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.component.http.HttpHeaderFilterStrategy;
+import org.apache.camel.impl.DefaultMessage;
+import org.apache.camel.spi.HeaderFilterStrategy;
+import org.apache.camel.util.ExchangeHelper;
+import org.apache.camel.util.MessageHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xnio.Pooled;
+
+/**
+ * DefaultUndertowHttpBinding represent binding used by default, if user doesn't provide any.
+ * By default {@link HttpHeaderFilterStrategy} is also used.
+ *
+ */
+public class DefaultUndertowHttpBinding implements UndertowHttpBinding {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultUndertowHttpBinding.class);
+
+    //use default filter strategy from Camel HTTP
+    private HeaderFilterStrategy headerFilterStrategy;
+
+    public DefaultUndertowHttpBinding() {
+        this.headerFilterStrategy = new HttpHeaderFilterStrategy();
+    }
+
+    public DefaultUndertowHttpBinding(HeaderFilterStrategy headerFilterStrategy) {
+        this.headerFilterStrategy = headerFilterStrategy;
+    }
+
+    public HeaderFilterStrategy getHeaderFilterStrategy() {
+        return headerFilterStrategy;
+    }
+
+    public void setHeaderFilterStrategy(HeaderFilterStrategy headerFilterStrategy) {
+        this.headerFilterStrategy = headerFilterStrategy;
+    }
+
+    @Override
+    public Message toCamelMessage(HttpServerExchange httpExchange, Exchange exchange) throws Exception {
+        Message result = new DefaultMessage();
+
+        populateCamelHeaders(httpExchange, result.getHeaders(), exchange);
+
+        //extract body if the method is allowed to have one
+        //body is extracted as byte[] then auto TypeConverter kicks in
+        if (Methods.POST.equals(httpExchange.getRequestMethod()) || Methods.PUT.equals(httpExchange.getRequestMethod())) {
+            byte[] bytes = readRequestBody(httpExchange);
+            result.setBody(bytes);
+        } else {
+            result.setBody(null);
+        }
+
+        return result;
+    }
+
+    @Override
+    public Message toCamelMessage(ClientExchange clientExchange, Exchange exchange) throws Exception {
+        Message result = new DefaultMessage();
+
+        //retrieve response headers
+        populateCamelHeaders(clientExchange.getResponse(), result.getHeaders(), exchange);
+
+        result.setBody(readResponseBody(clientExchange));
+
+        return result;
+
+    }
+
+    @Override
+    public void populateCamelHeaders(HttpServerExchange httpExchange, Map<String, Object> headersMap, Exchange exchange) throws Exception {
+        LOG.trace("populateCamelHeaders: {}");
+
+        // NOTE: these headers is applied using the same logic as camel-http/camel-jetty to be consistent
+        headersMap.put(Exchange.HTTP_METHOD, httpExchange.getRequestMethod().toString());
+        // strip query parameters from the uri
+        headersMap.put(Exchange.HTTP_URL, httpExchange.getRequestURL());
+        // uri is without the host and port
+        headersMap.put(Exchange.HTTP_URI, httpExchange.getRequestURI());
+        headersMap.put(Exchange.HTTP_QUERY, httpExchange.getQueryString());
+        headersMap.put(Exchange.HTTP_RAW_QUERY, httpExchange.getQueryString());
+
+
+        String path = httpExchange.getRequestPath();
+        headersMap.put(Exchange.HTTP_PATH, path);
+
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("HTTP-Method {}", httpExchange.getRequestMethod());
+            LOG.trace("HTTP-Uri {}", httpExchange.getRequestURI());
+        }
+
+        for (HttpString name : httpExchange.getRequestHeaders().getHeaderNames()) {
+            // mapping the content-type
+            //String name = httpName.toString();
+            if (name.toString().toLowerCase(Locale.US).equals("content-type")) {
+                name = ExchangeHeaders.CONTENT_TYPE;
+            }
+
+            if (name.toString().toLowerCase(Locale.US).equals("authorization")) {
+                String value = httpExchange.getRequestHeaders().get(name).toString();
+                // store a special header that this request was authenticated using HTTP Basic
+                if (value != null && value.trim().startsWith("Basic")) {
+                    if (headerFilterStrategy != null
+                        && !headerFilterStrategy.applyFilterToExternalHeaders(Exchange.AUTHENTICATION, "Basic", exchange)) {
+                        UndertowUtils.appendHeader(headersMap, Exchange.AUTHENTICATION, "Basic");
+                    }
+                }
+            }
+
+            // add the headers one by one, and use the header filter strategy
+            Iterator<?> it = httpExchange.getRequestHeaders().get(name).iterator();
+            while (it.hasNext()) {
+                Object value = it.next();
+                LOG.trace("HTTP-header: {}", value);
+                if (headerFilterStrategy != null
+                    && !headerFilterStrategy.applyFilterToExternalHeaders(name.toString(), value, exchange)) {
+                    UndertowUtils.appendHeader(headersMap, name.toString(), value);
+                }
+            }
+        }
+
+        //process uri parameters as headers
+        Map<String, Deque<String>> pathParameters = httpExchange.getQueryParameters();
+        //continue if the map is not empty, otherwise there are no params
+        if (!pathParameters.isEmpty()) {
+
+            for (Map.Entry<String, Deque<String>> entry : pathParameters.entrySet()) {
+                String name = entry.getKey();
+                Object values = entry.getValue();
+                Iterator<?> it = ObjectHelper.createIterator(values);
+                while (it.hasNext()) {
+                    Object value = it.next();
+                    LOG.trace("URI-Parameter: {}", value);
+                    if (headerFilterStrategy != null
+                        && !headerFilterStrategy.applyFilterToExternalHeaders(name, value, exchange)) {
+                        UndertowUtils.appendHeader(headersMap, name, value);
+                    }
+                }
+            }
+        }
+
+    }
+
+    @Override
+    public void populateCamelHeaders(ClientResponse response, Map<String, Object> headersMap, Exchange exchange) throws Exception {
+        LOG.trace("populateCamelHeaders: {}");
+
+        headersMap.put(Exchange.HTTP_RESPONSE_CODE, response.getResponseCode());
+
+        for (HttpString name : response.getResponseHeaders().getHeaderNames()) {
+            // mapping the content-type
+            //String name = httpName.toString();
+            if (name.toString().toLowerCase(Locale.US).equals("content-type")) {
+                name = ExchangeHeaders.CONTENT_TYPE;
+            }
+
+            if (name.toString().toLowerCase(Locale.US).equals("authorization")) {
+                String value = response.getResponseHeaders().get(name).toString();
+                // store a special header that this request was authenticated using HTTP Basic
+                if (value != null && value.trim().startsWith("Basic")) {
+                    if (headerFilterStrategy != null
+                        && !headerFilterStrategy.applyFilterToExternalHeaders(Exchange.AUTHENTICATION, "Basic", exchange)) {
+                        UndertowUtils.appendHeader(headersMap, Exchange.AUTHENTICATION, "Basic");
+                    }
+                }
+            }
+
+            // add the headers one by one, and use the header filter strategy
+            Iterator<?> it = response.getResponseHeaders().get(name).iterator();
+            while (it.hasNext()) {
+                Object value = it.next();
+                LOG.trace("HTTP-header: {}", value);
+                if (headerFilterStrategy != null
+                    && !headerFilterStrategy.applyFilterToExternalHeaders(name.toString(), value, exchange)) {
+                    UndertowUtils.appendHeader(headersMap, name.toString(), value);
+                }
+            }
+        }
+
+    }
+
+    @Override
+    public Object toHttpResponse(HttpServerExchange httpExchange, Message message) {
+        boolean failed = message.getExchange().isFailed();
+        int defaultCode = failed ? 500 : 200;
+
+        int code = message.getHeader(Exchange.HTTP_RESPONSE_CODE, defaultCode, int.class);
+
+        httpExchange.setResponseCode(code);
+
+        TypeConverter tc = message.getExchange().getContext().getTypeConverter();
+
+        //copy headers from Message to Response
+        for (Map.Entry<String, Object> entry : message.getHeaders().entrySet()) {
+            String key = entry.getKey();
+            Object value = entry.getValue();
+            // use an iterator as there can be multiple values. (must not use a delimiter)
+            final Iterator<?> it = ObjectHelper.createIterator(value, null);
+            while (it.hasNext()) {
+                String headerValue = tc.convertTo(String.class, it.next());
+                if (headerValue != null && headerFilterStrategy != null
+                    && !headerFilterStrategy.applyFilterToCamelHeaders(key, headerValue, message.getExchange())) {
+                    LOG.trace("HTTP-Header: {}={}", key, headerValue);
+                    httpExchange.getResponseHeaders().add(new HttpString(key), headerValue);
+                }
+            }
+        }
+
+        Exception exception = message.getExchange().getException();
+
+        if (exception != null) {
+            httpExchange.getResponseHeaders().put(Headers.CONTENT_TYPE, MimeMappings.DEFAULT_MIME_MAPPINGS.get("txt"));
+
+            StringWriter sw = new StringWriter();
+            PrintWriter pw = new PrintWriter(sw);
+            exception.printStackTrace(pw);
+
+            String exceptionMessage = sw.toString();
+
+            ExchangeHelper.setFailureHandled(message.getExchange());
+            return exceptionMessage;
+        }
+
+        // set the content type in the response.
+        String contentType = MessageHelper.getContentType(message);
+        if (contentType != null) {
+            // set content-type
+            httpExchange.getResponseHeaders().put(Headers.CONTENT_TYPE, contentType);
+            LOG.trace("Content-Type: {}", contentType);
+        }
+
+        return message.getBody();
+
+    }
+
+    @Override
+    public Object toHttpRequest(ClientRequest clientRequest, Message message) {
+
+        Object body = message.getBody();
+
+        String method = message.getHeader(Exchange.HTTP_METHOD, String.class);
+
+        if (method == null) {
+            //fallback if method is not defined, check the body
+            if (body == null) {
+                clientRequest.setMethod(Methods.GET);
+            } else {
+                clientRequest.setMethod(Methods.POST);
+            }
+        } else {
+            //method set, use it
+            clientRequest.setMethod(new HttpString(method));
+        }
+
+        // set the content type in the response.
+        String contentType = MessageHelper.getContentType(message);
+        if (contentType != null) {
+            // set content-type
+            clientRequest.getRequestHeaders().put(Headers.CONTENT_TYPE, contentType);
+            LOG.trace("Content-Type: {}", contentType);
+        }
+
+        TypeConverter tc = message.getExchange().getContext().getTypeConverter();
+
+        //copy headers from Message to Request
+        for (Map.Entry<String, Object> entry : message.getHeaders().entrySet()) {
+            String key = entry.getKey();
+            Object value = entry.getValue();
+            // use an iterator as there can be multiple values. (must not use a delimiter)
+            final Iterator<?> it = ObjectHelper.createIterator(value, null);
+            while (it.hasNext()) {
+                String headerValue = tc.convertTo(String.class, it.next());
+                if (headerValue != null && headerFilterStrategy != null
+                    && !headerFilterStrategy.applyFilterToCamelHeaders(key, headerValue, message.getExchange())) {
+                    LOG.trace("HTTP-Header: {}={}", key, headerValue);
+                    clientRequest.getRequestHeaders().add(new HttpString(key), headerValue);
+                }
+            }
+        }
+
+
+        return body;
+    }
+
+    private byte[] readRequestBody(HttpServerExchange httpExchange) throws IOException {
+        Pooled<ByteBuffer> pooledByteBuffer = httpExchange.getConnection().getBufferPool().allocate();
+        ByteBuffer byteBuffer = pooledByteBuffer.getResource();
+
+        byteBuffer.clear();
+
+        httpExchange.getRequestChannel().read(byteBuffer);
+        int pos = byteBuffer.position();
+        byteBuffer.rewind();
+        byte[] bytes = new byte[pos];
+        byteBuffer.get(bytes);
+
+        byteBuffer.clear();
+        pooledByteBuffer.free();
+        return bytes;
+    }
+
+    private byte[] readResponseBody(ClientExchange httpExchange) throws IOException {
+        Pooled<ByteBuffer> pooledByteBuffer = httpExchange.getConnection().getBufferPool().allocate();
+        ByteBuffer byteBuffer = pooledByteBuffer.getResource();
+
+        byteBuffer.clear();
+
+        httpExchange.getResponseChannel().read(byteBuffer);
+        int pos = byteBuffer.position();
+        byteBuffer.rewind();
+        byte[] bytes = new byte[pos];
+        byteBuffer.get(bytes);
+
+        byteBuffer.clear();
+        pooledByteBuffer.free();
+        return bytes;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/100b2f40/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/ExchangeHeaders.java
----------------------------------------------------------------------
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/ExchangeHeaders.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/ExchangeHeaders.java
new file mode 100644
index 0000000..54f9d96
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/ExchangeHeaders.java
@@ -0,0 +1,176 @@
+/**
+ * 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;
+
+import io.undertow.util.HttpString;
+
+/**
+ * Copy of {@link org.apache.camel.Exchange} headers fields, to return them as {@link HttpString} for Undertow
+ *
+ */
+public final class ExchangeHeaders {
+
+    public static final HttpString AUTHENTICATION = new HttpString("CamelAuthentication");
+    public static final HttpString AUTHENTICATION_FAILURE_POLICY_ID = new HttpString("CamelAuthenticationFailurePolicyId");
+    public static final HttpString ACCEPT_CONTENT_TYPE = new HttpString("CamelAcceptContentType");
+    public static final HttpString AGGREGATED_SIZE = new HttpString("CamelAggregatedSize");
+    public static final HttpString AGGREGATED_TIMEOUT = new HttpString("CamelAggregatedTimeout");
+    public static final HttpString AGGREGATED_COMPLETED_BY = new HttpString("CamelAggregatedCompletedBy");
+    public static final HttpString AGGREGATED_CORRELATION_KEY = new HttpString("CamelAggregatedCorrelationKey");
+    public static final HttpString AGGREGATION_STRATEGY = new HttpString("CamelAggregationStrategy");
+    public static final HttpString AGGREGATION_COMPLETE_ALL_GROUPS = new HttpString("CamelAggregationCompleteAllGroups");
+    public static final HttpString AGGREGATION_COMPLETE_ALL_GROUPS_INCLUSIVE = new HttpString("CamelAggregationCompleteAllGroupsInclusive");
+    public static final HttpString ASYNC_WAIT = new HttpString("CamelAsyncWait");
+
+    public static final HttpString BATCH_INDEX = new HttpString("CamelBatchIndex");
+    public static final HttpString BATCH_SIZE = new HttpString("CamelBatchSize");
+    public static final HttpString BATCH_COMPLETE = new HttpString("CamelBatchComplete");
+    public static final HttpString BEAN_METHOD_NAME = new HttpString("CamelBeanMethodName");
+    public static final HttpString BEAN_MULTI_PARAMETER_ARRAY = new HttpString("CamelBeanMultiParameterArray");
+    public static final HttpString BINDING = new HttpString("CamelBinding");
+    // do not prefix with Camel and use lower-case starting letter as its a shared key
+    // used across other Apache products such as AMQ, SMX etc.
+    public static final HttpString BREADCRUMB_ID = new HttpString("breadcrumbId");
+
+    public static final HttpString CHARSET_NAME = new HttpString("CamelCharsetName");
+    public static final HttpString CREATED_TIMESTAMP = new HttpString("CamelCreatedTimestamp");
+    public static final HttpString CONTENT_ENCODING = new HttpString("Content-Encoding");
+    public static final HttpString CONTENT_LENGTH = new HttpString("Content-Length");
+    public static final HttpString CONTENT_TYPE = new HttpString("Content-Type");
+    public static final HttpString CORRELATION_ID = new HttpString("CamelCorrelationId");
+
+    public static final HttpString DATASET_INDEX = new HttpString("CamelDataSetIndex");
+    public static final HttpString DEFAULT_CHARSET_PROPERTY = new HttpString("org.apache.camel.default.charset");
+    public static final HttpString DESTINATION_OVERRIDE_URL = new HttpString("CamelDestinationOverrideUrl");
+    public static final HttpString DISABLE_HTTP_STREAM_CACHE = new HttpString("CamelDisableHttpStreamCache");
+    public static final HttpString DUPLICATE_MESSAGE = new HttpString("CamelDuplicateMessage");
+
+    public static final HttpString DOCUMENT_BUILDER_FACTORY = new HttpString("CamelDocumentBuilderFactory");
+
+    public static final HttpString EXCEPTION_CAUGHT = new HttpString("CamelExceptionCaught");
+    public static final HttpString EXCEPTION_HANDLED = new HttpString("CamelExceptionHandled");
+    public static final HttpString EVALUATE_EXPRESSION_RESULT = new HttpString("CamelEvaluateExpressionResult");
+    public static final HttpString ERRORHANDLER_HANDLED = new HttpString("CamelErrorHandlerHandled");
+    public static final HttpString EXTERNAL_REDELIVERED = new HttpString("CamelExternalRedelivered");
+
+    public static final HttpString FAILURE_HANDLED = new HttpString("CamelFailureHandled");
+    public static final HttpString FAILURE_ENDPOINT = new HttpString("CamelFailureEndpoint");
+    public static final HttpString FAILURE_ROUTE_ID = new HttpString("CamelFailureRouteId");
+    public static final HttpString FILTER_NON_XML_CHARS = new HttpString("CamelFilterNonXmlChars");
+    public static final HttpString FILE_LOCAL_WORK_PATH = new HttpString("CamelFileLocalWorkPath");
+    public static final HttpString FILE_NAME = new HttpString("CamelFileName");
+    public static final HttpString FILE_NAME_ONLY = new HttpString("CamelFileNameOnly");
+    public static final HttpString FILE_NAME_PRODUCED = new HttpString("CamelFileNameProduced");
+    public static final HttpString FILE_NAME_CONSUMED = new HttpString("CamelFileNameConsumed");
+    public static final HttpString FILE_PATH = new HttpString("CamelFilePath");
+    public static final HttpString FILE_PARENT = new HttpString("CamelFileParent");
+    public static final HttpString FILE_LAST_MODIFIED = new HttpString("CamelFileLastModified");
+    public static final HttpString FILE_LENGTH = new HttpString("CamelFileLength");
+    public static final HttpString FILTER_MATCHED = new HttpString("CamelFilterMatched");
+    public static final HttpString FILE_LOCK_FILE_ACQUIRED = new HttpString("CamelFileLockFileAcquired");
+    public static final HttpString FILE_LOCK_FILE_NAME = new HttpString("CamelFileLockFileName");
+
+    public static final HttpString GROUPED_EXCHANGE = new HttpString("CamelGroupedExchange");
+
+    public static final HttpString HTTP_BASE_URI = new HttpString("CamelHttpBaseUri");
+    public static final HttpString HTTP_CHARACTER_ENCODING = new HttpString("CamelHttpCharacterEncoding");
+    public static final HttpString HTTP_METHOD = new HttpString("CamelHttpMethod");
+    public static final HttpString HTTP_PATH = new HttpString("CamelHttpPath");
+    public static final HttpString HTTP_PROTOCOL_VERSION = new HttpString("CamelHttpProtocolVersion");
+    public static final HttpString HTTP_QUERY = new HttpString("CamelHttpQuery");
+    public static final HttpString HTTP_RAW_QUERY = new HttpString("CamelHttpRawQuery");
+    public static final HttpString HTTP_RESPONSE_CODE = new HttpString("CamelHttpResponseCode");
+    public static final HttpString HTTP_URI = new HttpString("CamelHttpUri");
+    public static final HttpString HTTP_URL = new HttpString("CamelHttpUrl");
+    public static final HttpString HTTP_CHUNKED = new HttpString("CamelHttpChunked");
+    public static final HttpString HTTP_SERVLET_REQUEST = new HttpString("CamelHttpServletRequest");
+    public static final HttpString HTTP_SERVLET_RESPONSE = new HttpString("CamelHttpServletResponse");
+
+    public static final HttpString INTERCEPTED_ENDPOINT = new HttpString("CamelInterceptedEndpoint");
+    public static final HttpString INTERCEPT_SEND_TO_ENDPOINT_WHEN_MATCHED = new HttpString("CamelInterceptSendToEndpointWhenMatched");
+
+    public static final HttpString LANGUAGE_SCRIPT = new HttpString("CamelLanguageScript");
+    public static final HttpString LOG_DEBUG_BODY_MAX_CHARS = new HttpString("CamelLogDebugBodyMaxChars");
+    public static final HttpString LOG_DEBUG_BODY_STREAMS = new HttpString("CamelLogDebugStreams");
+    public static final HttpString LOOP_INDEX = new HttpString("CamelLoopIndex");
+    public static final HttpString LOOP_SIZE = new HttpString("CamelLoopSize");
+
+    public static final HttpString MAXIMUM_CACHE_POOL_SIZE = new HttpString("CamelMaximumCachePoolSize");
+    public static final HttpString MAXIMUM_ENDPOINT_CACHE_SIZE = new HttpString("CamelMaximumEndpointCacheSize");
+    public static final HttpString MESSAGE_HISTORY = new HttpString("CamelMessageHistory");
+    public static final HttpString MULTICAST_INDEX = new HttpString("CamelMulticastIndex");
+    public static final HttpString MULTICAST_COMPLETE = new HttpString("CamelMulticastComplete");
+
+    public static final HttpString NOTIFY_EVENT = new HttpString("CamelNotifyEvent");
+
+    public static final HttpString ON_COMPLETION = new HttpString("CamelOnCompletion");
+    public static final HttpString OVERRULE_FILE_NAME = new HttpString("CamelOverruleFileName");
+
+    public static final HttpString PARENT_UNIT_OF_WORK = new HttpString("CamelParentUnitOfWork");
+
+    public static final HttpString RECIPIENT_LIST_ENDPOINT = new HttpString("CamelRecipientListEndpoint");
+    public static final HttpString RECEIVED_TIMESTAMP = new HttpString("CamelReceivedTimestamp");
+    public static final HttpString REDELIVERED = new HttpString("CamelRedelivered");
+    public static final HttpString REDELIVERY_COUNTER = new HttpString("CamelRedeliveryCounter");
+    public static final HttpString REDELIVERY_MAX_COUNTER = new HttpString("CamelRedeliveryMaxCounter");
+    public static final HttpString REDELIVERY_EXHAUSTED = new HttpString("CamelRedeliveryExhausted");
+    public static final HttpString REDELIVERY_DELAY = new HttpString("CamelRedeliveryDelay");
+    public static final HttpString ROLLBACK_ONLY = new HttpString("CamelRollbackOnly");
+    public static final HttpString ROLLBACK_ONLY_LAST = new HttpString("CamelRollbackOnlyLast");
+    public static final HttpString ROUTE_STOP = new HttpString("CamelRouteStop");
+
+    public static final HttpString SAXPARSER_FACTORY = new HttpString("CamelSAXParserFactory");
+
+    public static final HttpString SOAP_ACTION = new HttpString("CamelSoapAction");
+    public static final HttpString SKIP_GZIP_ENCODING = new HttpString("CamelSkipGzipEncoding");
+    public static final HttpString SKIP_WWW_FORM_URLENCODED = new HttpString("CamelSkipWwwFormUrlEncoding");
+    public static final HttpString SLIP_ENDPOINT = new HttpString("CamelSlipEndpoint");
+    public static final HttpString SPLIT_INDEX = new HttpString("CamelSplitIndex");
+    public static final HttpString SPLIT_COMPLETE = new HttpString("CamelSplitComplete");
+    public static final HttpString SPLIT_SIZE = new HttpString("CamelSplitSize");
+
+    public static final HttpString TIMER_COUNTER = new HttpString("CamelTimerCounter");
+    public static final HttpString TIMER_FIRED_TIME = new HttpString("CamelTimerFiredTime");
+    public static final HttpString TIMER_NAME = new HttpString("CamelTimerName");
+    public static final HttpString TIMER_PERIOD = new HttpString("CamelTimerPeriod");
+    public static final HttpString TIMER_TIME = new HttpString("CamelTimerTime");
+    public static final HttpString TO_ENDPOINT = new HttpString("CamelToEndpoint");
+    public static final HttpString TRACE_EVENT = new HttpString("CamelTraceEvent");
+    public static final HttpString TRACE_EVENT_NODE_ID = new HttpString("CamelTraceEventNodeId");
+    public static final HttpString TRACE_EVENT_TIMESTAMP = new HttpString("CamelTraceEventTimestamp");
+    public static final HttpString TRACE_EVENT_EXCHANGE = new HttpString("CamelTraceEventExchange");
+    public static final HttpString TRY_ROUTE_BLOCK = new HttpString("TryRouteBlock");
+    public static final HttpString TRANSFER_ENCODING = new HttpString("Transfer-Encoding");
+
+    public static final HttpString UNIT_OF_WORK_EXHAUSTED = new HttpString("CamelUnitOfWorkExhausted");
+
+    /**
+     * @deprecated UNIT_OF_WORK_PROCESS_SYNC is not in use and will be removed in future Camel release
+     */
+    @Deprecated
+    public static final HttpString UNIT_OF_WORK_PROCESS_SYNC = new HttpString("CamelUnitOfWorkProcessSync");
+
+    public static final HttpString XSLT_FILE_NAME = new HttpString("CamelXsltFileName");
+    public static final HttpString XSLT_ERROR = new HttpString("CamelXsltError");
+    public static final HttpString XSLT_FATAL_ERROR = new HttpString("CamelXsltFatalError");
+    public static final HttpString XSLT_WARNING = new HttpString("CamelXsltWarning");
+
+    private ExchangeHeaders() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/100b2f40/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..91bd8a8
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java
@@ -0,0 +1,281 @@
+/**
+ * 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;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import javax.net.ssl.SSLContext;
+
+import io.undertow.Handlers;
+import io.undertow.Undertow;
+import io.undertow.server.handlers.PathHandler;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Consumer;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Processor;
+import org.apache.camel.component.http.HttpBinding;
+import org.apache.camel.component.http.HttpClientConfigurer;
+import org.apache.camel.component.http.HttpComponent;
+import org.apache.camel.component.http.HttpConfiguration;
+import org.apache.camel.component.undertow.handlers.HttpCamelHandler;
+import org.apache.camel.component.undertow.handlers.NotFoundHandler;
+import org.apache.camel.spi.HeaderFilterStrategy;
+import org.apache.camel.spi.RestConfiguration;
+import org.apache.camel.spi.RestConsumerFactory;
+import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.URISupport;
+import org.apache.camel.util.UnsafeUriCharactersEncoder;
+import org.apache.camel.util.jsse.SSLContextParameters;
+import org.apache.commons.httpclient.HttpConnectionManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Represents the component that manages {@link UndertowEndpoint}.
+ *
+ */
+public class UndertowComponent extends HttpComponent implements RestConsumerFactory {
+    private static final Logger LOG = LoggerFactory.getLogger(UndertowEndpoint.class);
+
+    private UndertowHttpBinding undertowHttpBinding;
+    private Map<Integer, UndertowRegistry> serversRegistry = new HashMap<Integer, UndertowRegistry>();
+
+    public UndertowComponent() {
+        this.undertowHttpBinding = new DefaultUndertowHttpBinding();
+    }
+
+    @Override
+    protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+        //extract parameters from URI
+        Boolean matchOnUriPrefix = getAndRemoveParameter(parameters, "matchOnUriPrefix", Boolean.class);
+        HeaderFilterStrategy headerFilterStrategy = resolveAndRemoveReferenceParameter(parameters, "headerFilterStrategy", HeaderFilterStrategy.class);
+        SSLContextParameters sslContextParameters = resolveAndRemoveReferenceParameter(parameters, "sslContextParametersRef", SSLContextParameters.class);
+        Boolean throwExceptionOnFailure = getAndRemoveParameter(parameters, "throwExceptionOnFailure", Boolean.class);
+        Boolean transferException = getAndRemoveParameter(parameters, "transferException", Boolean.class);
+
+        String httpMethodRestrict = getAndRemoveParameter(parameters, "httpMethodRestrict", String.class);
+
+        System.out.println("Remaining: " + remaining);
+        String address = remaining;
+        URI httpUri = new URI(UnsafeUriCharactersEncoder.encodeHttpURI(address));
+        URI endpointUri = URISupport.createRemainingURI(httpUri, parameters);
+
+        UndertowEndpoint endpoint = new UndertowEndpoint(endpointUri.toString(), this, httpUri);
+
+        if (endpoint.getUndertowHttpBinding() == null) {
+            endpoint.setUndertowHttpBinding(undertowHttpBinding);
+        }
+
+        //set parameters if they exists in URI
+        if (httpMethodRestrict != null) {
+            endpoint.setHttpMethodRestrict(httpMethodRestrict);
+        }
+        if (matchOnUriPrefix != null) {
+            endpoint.setMatchOnUriPrefix(matchOnUriPrefix);
+        }
+        if (headerFilterStrategy != null) {
+            endpoint.setHeaderFilterStrategy(headerFilterStrategy);
+        }
+        if (sslContextParameters != null) {
+            SSLContext sslContext = sslContextParameters.createSSLContext();
+            endpoint.setSslContext(sslContext);
+        }
+        if (throwExceptionOnFailure != null) {
+            endpoint.setThrowExceptionOnFailure(throwExceptionOnFailure);
+        }
+        if (transferException != null) {
+            endpoint.setTransferException(transferException);
+        }
+
+        setProperties(endpoint, parameters);
+        return endpoint;
+    }
+
+    @Override
+    public Consumer createConsumer(CamelContext camelContext, Processor processor, String verb, String basePath, String uriTemplate,
+                                   String consumes, String produces, Map<String, Object> parameters) throws Exception {
+        String path = basePath;
+        if (uriTemplate != null) {
+            // make sure to avoid double slashes
+            if (uriTemplate.startsWith("/")) {
+                path = path + uriTemplate;
+            } else {
+                path = path + "/" + uriTemplate;
+            }
+        }
+        path = FileUtil.stripLeadingSeparator(path);
+        String scheme = "http";
+        String host = "";
+        int port = 0;
+        RestConfiguration config = getCamelContext().getRestConfiguration();
+        if (config.getComponent() == null || config.getComponent().equals("undertow")) {
+            if (config.getScheme() != null) {
+                scheme = config.getScheme();
+            }
+            if (config.getHost() != null) {
+                host = config.getHost();
+            }
+            int num = config.getPort();
+            if (num > 0) {
+                port = num;
+            }
+        }
+
+        Map<String, Object> map = new HashMap<String, Object>();
+        // build query string, and append any endpoint configuration properties
+        if (config != null && (config.getComponent() == null || config.getComponent().equals("undertow"))) {
+            // setup endpoint options
+            if (config.getEndpointProperties() != null && !config.getEndpointProperties().isEmpty()) {
+                map.putAll(config.getEndpointProperties());
+            }
+        }
+
+        String query = URISupport.createQueryString(map);
+
+        String url = "undertow:%s://%s:%s/%s";
+        url = String.format(url, scheme, host, port, path);
+        if (!query.isEmpty()) {
+            url = url + "&" + query;
+        }
+
+        UndertowEndpoint endpoint = camelContext.getEndpoint(url, UndertowEndpoint.class);
+        setProperties(endpoint, parameters);
+
+        Consumer consumer = endpoint.createConsumer(processor);
+
+        return consumer;
+
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        super.doStop();
+    }
+
+    protected Undertow rebuildServer(UndertowRegistry registy) {
+        Undertow.Builder result = Undertow.builder();
+        int port = registy.getPort();
+        if (registy.getSslContext() != null) {
+            result = result.addHttpsListener(registy.getPort(), registy.getHost(), registy.getSslContext());
+        } else {
+            result = result.addHttpListener(registy.getPort(), registy.getHost());
+        }
+        PathHandler path = Handlers.path(new NotFoundHandler());
+        for (URI key : registy.getConsumersRegistry().keySet()) {
+            UndertowConsumer consumer = registy.getConsumersRegistry().get(key);
+            URI httpUri = consumer.getEndpoint().getHttpURI();
+            if (consumer.getEndpoint().getMatchOnUriPrefix()) {
+                path.addPrefixPath(httpUri.getPath(), new HttpCamelHandler(consumer));
+
+            } else {
+                path.addExactPath(httpUri.getPath(), new HttpCamelHandler(consumer));
+
+            }
+            LOG.debug("::Rebuild for path: {}", httpUri.getPath());
+        }
+        result = result.setHandler(path);
+        return result.build();
+    }
+
+    public void registerConsumer(UndertowConsumer consumer) {
+        int port = consumer.getEndpoint().getHttpURI().getPort();
+        if (serversRegistry.containsKey(port)) {
+            //server listens on port, we need add configuration for path
+            UndertowRegistry undertowRegistry = serversRegistry.get(port);
+            undertowRegistry.registerConsumer(consumer);
+        } else {
+            //create new server to listen on specified port
+            serversRegistry.put(port, new UndertowRegistry(consumer, port));
+        }
+    }
+
+    public void unregisterConsumer(UndertowConsumer consumer) {
+        int port = consumer.getEndpoint().getHttpURI().getPort();
+        if (serversRegistry.containsKey(port)) {
+            serversRegistry.get(port).unregisterConsumer(consumer);
+        }
+        if (serversRegistry.get(port).isEmpty()) {
+            //if there no Consumer left, we can shut down server
+            serversRegistry.get(port).getServer().stop();
+            serversRegistry.remove(port);
+        } else {
+            //call startServer to rebuild otherwise
+            startServer(consumer);
+        }
+    }
+
+    public void startServer(UndertowConsumer consumer) {
+        int port = consumer.getEndpoint().getHttpURI().getPort();
+        LOG.info("Starting server on port: {}", port);
+        UndertowRegistry undertowRegistry = serversRegistry.get(port);
+
+        if (undertowRegistry.getServer() != null) {
+            //server is running, we need to stop it first and then rebuild
+            undertowRegistry.getServer().stop();
+        }
+        Undertow newServer = rebuildServer(undertowRegistry);
+        newServer.start();
+        undertowRegistry.setServer(newServer);
+    }
+
+    /**
+     * To use the custom HttpClientConfigurer to perform configuration of the HttpClient that will be used.
+     *
+     * @param httpClientConfigurer
+     */
+    @Override
+    public void setHttpClientConfigurer(HttpClientConfigurer httpClientConfigurer) {
+        super.setHttpClientConfigurer(httpClientConfigurer);
+    }
+
+    /**
+     * To use a custom HttpConnectionManager to manage connections
+     *
+     * @param httpConnectionManager
+     */
+    @Override
+    public void setHttpConnectionManager(HttpConnectionManager httpConnectionManager) {
+        super.setHttpConnectionManager(httpConnectionManager);
+    }
+
+    /**
+     * To use a custom HttpBinding to control the mapping between Camel message and HttpClient.
+     *
+     * @param httpBinding
+     */
+    @Override
+    public void setHttpBinding(HttpBinding httpBinding) {
+        super.setHttpBinding(httpBinding);
+    }
+
+    /**
+     * To use the shared HttpConfiguration as base configuration.
+     *
+     * @param httpConfiguration
+     */
+    @Override
+    public void setHttpConfiguration(HttpConfiguration httpConfiguration) {
+        super.setHttpConfiguration(httpConfiguration);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/100b2f40/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowConsumer.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..52c0cbf
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowConsumer.java
@@ -0,0 +1,58 @@
+/**
+ * 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;
+
+import org.apache.camel.Processor;
+import org.apache.camel.impl.DefaultConsumer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The Undertow consumer.
+ *
+ */
+public class UndertowConsumer extends DefaultConsumer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(UndertowConsumer.class);
+
+    public UndertowConsumer(UndertowEndpoint endpoint, Processor processor) {
+        super(endpoint, processor);
+
+    }
+
+    @Override
+    public UndertowEndpoint getEndpoint() {
+        return (UndertowEndpoint) super.getEndpoint();
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+        LOG.debug("Undertow consumer is starting");
+        getEndpoint().getComponent().registerConsumer(this);
+        getEndpoint().getComponent().startServer(this);
+    }
+
+    @Override
+    protected void doStop() {
+        LOG.debug("Undertow consumer is stopping");
+        getEndpoint().getComponent().unregisterConsumer(this);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/100b2f40/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowEndpoint.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..064f18c
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowEndpoint.java
@@ -0,0 +1,196 @@
+/**
+ * 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;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import javax.net.ssl.SSLContext;
+
+import io.undertow.server.HttpServerExchange;
+import org.apache.camel.Consumer;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.PollingConsumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.impl.DefaultEndpoint;
+import org.apache.camel.spi.HeaderFilterStrategy;
+import org.apache.camel.spi.HeaderFilterStrategyAware;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Represents an Undertow endpoint.
+ *
+ */
+@UriEndpoint(scheme = "undertow", title = "Undertow", syntax = "undertow:host:port/path",
+    consumerClass = UndertowConsumer.class, label = "http")
+public class UndertowEndpoint extends DefaultEndpoint implements HeaderFilterStrategyAware {
+    private static final Logger LOG = LoggerFactory.getLogger(UndertowEndpoint.class);
+
+    private UndertowHttpBinding undertowHttpBinding;
+    private UndertowComponent component;
+    private HeaderFilterStrategy headerFilterStrategy;
+    private SSLContext sslContext;
+
+    @UriPath
+    private URI httpURI;
+    @UriParam
+    private String httpMethodRestrict;
+    @UriParam
+    private Boolean matchOnUriPrefix = true;
+    @UriParam
+    private Boolean throwExceptionOnFailure;
+    @UriParam
+    private Boolean transferException;
+
+    public UndertowEndpoint(String uri, UndertowComponent component, URI httpURI) throws URISyntaxException {
+        super(uri, component);
+        this.component = component;
+        this.httpURI = httpURI;
+    }
+
+    @Override
+    public Producer createProducer() throws Exception {
+        return new UndertowProducer(this);
+    }
+
+    public Exchange createExchange(HttpServerExchange httpExchange) throws Exception {
+        Exchange exchange = createExchange();
+
+        Message in = getUndertowHttpBinding().toCamelMessage(httpExchange, exchange);
+
+        exchange.setProperty(Exchange.CHARSET_NAME, httpExchange.getRequestCharset());
+        in.setHeader(Exchange.HTTP_CHARACTER_ENCODING, httpExchange.getRequestCharset());
+
+        exchange.setIn(in);
+        return exchange;
+    }
+
+    public Consumer createConsumer(Processor processor) throws Exception {
+        return new UndertowConsumer(this, processor);
+    }
+
+    @Override
+    public PollingConsumer createPollingConsumer() throws Exception {
+        //throw exception as polling consumer is not supported
+        throw new UnsupportedOperationException("This component does not support polling consumer");
+    }
+
+    public boolean isSingleton() {
+        return true;
+    }
+
+    public URI getHttpURI() {
+        return httpURI;
+    }
+
+    /**
+     * Set full HTTP URI
+     * @param httpURI
+     */
+    public void setHttpURI(URI httpURI) {
+        this.httpURI = httpURI;
+    }
+
+
+    public String getHttpMethodRestrict() {
+        return httpMethodRestrict;
+    }
+
+    /**
+     * Configure set of allowed HTTP request method
+     * @param httpMethodRestrict
+     */
+    public void setHttpMethodRestrict(String httpMethodRestrict) {
+        this.httpMethodRestrict = httpMethodRestrict;
+    }
+
+    public Boolean getMatchOnUriPrefix() {
+        return matchOnUriPrefix;
+    }
+
+    /**
+     * Set if URI should be matched on prefix
+     * @param matchOnUriPrefix
+     */
+    public void setMatchOnUriPrefix(Boolean matchOnUriPrefix) {
+        this.matchOnUriPrefix = matchOnUriPrefix;
+    }
+
+    public HeaderFilterStrategy getHeaderFilterStrategy() {
+        return headerFilterStrategy;
+    }
+
+    public void setHeaderFilterStrategy(HeaderFilterStrategy headerFilterStrategy) {
+        this.headerFilterStrategy = headerFilterStrategy;
+        undertowHttpBinding.setHeaderFilterStrategy(headerFilterStrategy);
+    }
+
+    public SSLContext getSslContext() {
+        return sslContext;
+    }
+
+    public void setSslContext(SSLContext sslContext) {
+        this.sslContext = sslContext;
+    }
+
+    public Boolean getThrowExceptionOnFailure() {
+        return throwExceptionOnFailure;
+    }
+
+    /**
+     * Configure if exception should be thrown on failure
+     * @param throwExceptionOnFailure
+     */
+    public void setThrowExceptionOnFailure(Boolean throwExceptionOnFailure) {
+        this.throwExceptionOnFailure = throwExceptionOnFailure;
+    }
+
+    public Boolean getTransferException() {
+        return transferException;
+    }
+
+    /**
+     * Configure if expcetion should be transfered to client
+     * @param transferException
+     */
+    public void setTransferException(Boolean transferException) {
+        this.transferException = transferException;
+    }
+
+    public UndertowHttpBinding getUndertowHttpBinding() {
+        return undertowHttpBinding;
+    }
+
+    public void setUndertowHttpBinding(UndertowHttpBinding undertowHttpBinding) {
+        this.undertowHttpBinding = undertowHttpBinding;
+    }
+
+    @Override
+    public UndertowComponent getComponent() {
+        return component;
+    }
+
+    public void setComponent(UndertowComponent component) {
+        this.component = component;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/100b2f40/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHttpBinding.java
----------------------------------------------------------------------
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHttpBinding.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHttpBinding.java
new file mode 100644
index 0000000..b9aad5b
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHttpBinding.java
@@ -0,0 +1,50 @@
+/**
+ * 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;
+
+import java.util.Map;
+
+import io.undertow.client.ClientExchange;
+import io.undertow.client.ClientRequest;
+import io.undertow.client.ClientResponse;
+import io.undertow.server.HttpServerExchange;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.spi.HeaderFilterStrategy;
+
+/**
+ * Interface to define custom binding for the component
+ *
+ */
+public interface UndertowHttpBinding {
+
+    Message toCamelMessage(HttpServerExchange httpExchange, Exchange exchange) throws Exception;
+
+    Message toCamelMessage(ClientExchange clientExchange, Exchange exchange) throws Exception;
+
+    void populateCamelHeaders(HttpServerExchange httpExchange, Map<String, Object> headerMap, Exchange exchange) throws Exception;
+
+    void populateCamelHeaders(ClientResponse response, Map<String, Object> headerMap, Exchange exchange) throws Exception;
+
+    Object toHttpResponse(HttpServerExchange httpExchange, Message message);
+
+    Object toHttpRequest(ClientRequest clientRequest, Message message);
+
+    void setHeaderFilterStrategy(HeaderFilterStrategy headerFilterStrategy);
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/100b2f40/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowProducer.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..4136824
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowProducer.java
@@ -0,0 +1,159 @@
+/**
+ * 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;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import io.undertow.client.ClientCallback;
+import io.undertow.client.ClientConnection;
+import io.undertow.client.ClientExchange;
+import io.undertow.client.ClientRequest;
+import io.undertow.client.UndertowClient;
+import io.undertow.util.Headers;
+import io.undertow.util.Protocols;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.impl.DefaultProducer;
+import org.apache.camel.util.ExchangeHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xnio.BufferAllocator;
+import org.xnio.ByteBufferSlicePool;
+import org.xnio.IoFuture;
+import org.xnio.OptionMap;
+import org.xnio.Xnio;
+import org.xnio.XnioWorker;
+
+/**
+ * The Undertow producer.
+ *
+ * The implementation of Producer is considered as experimental. The Undertow client classes are not thread safe,
+ * their purpose is for the reverse proxy usage inside Undertow itself. This may change in the future versions and
+ * general purpose HTTP client wrapper will be added. Therefore this Producer may be changed too.
+ *
+ */
+public class UndertowProducer extends DefaultProducer {
+    private static final Logger LOG = LoggerFactory.getLogger(UndertowProducer.class);
+    private UndertowEndpoint endpoint;
+
+    public UndertowProducer(UndertowEndpoint endpoint) {
+        super(endpoint);
+        this.endpoint = endpoint;
+    }
+
+    @Override
+    public UndertowEndpoint getEndpoint() {
+        return endpoint;
+    }
+
+    public void setEndpoint(UndertowEndpoint endpoint) {
+        this.endpoint = endpoint;
+    }
+
+    @Override
+    public void process(Exchange exchange) throws Exception {
+        LOG.info("Producer endpoint uri " + endpoint.getHttpURI());
+
+        final UndertowClient client = UndertowClient.getInstance();
+        XnioWorker worker = Xnio.getInstance().createWorker(OptionMap.EMPTY);
+        IoFuture<ClientConnection> connect = client.connect(endpoint.getHttpURI(), worker, new ByteBufferSlicePool(BufferAllocator.DIRECT_BYTE_BUFFER_ALLOCATOR, 8192, 8192 * 8192), OptionMap.EMPTY);
+
+        ClientRequest request = new ClientRequest();
+        request.setProtocol(Protocols.HTTP_1_1);
+
+        Object body = getRequestBody(request, exchange);
+
+
+        TypeConverter tc = endpoint.getCamelContext().getTypeConverter();
+        ByteBuffer bodyAsByte = tc.convertTo(ByteBuffer.class, body);
+
+        if (body != null) {
+            request.getRequestHeaders().put(Headers.CONTENT_LENGTH, bodyAsByte.array().length);
+        }
+
+        connect.get().sendRequest(request, new UndertowProducerCallback(bodyAsByte, exchange));
+
+    }
+
+    private Object getRequestBody(ClientRequest request, Exchange camelExchange) {
+        Object result;
+        result = endpoint.getUndertowHttpBinding().toHttpRequest(request, camelExchange.getIn());
+        return result;
+    }
+
+    /**
+     * Everything important happens in callback
+     */
+    private class UndertowProducerCallback implements ClientCallback<ClientExchange> {
+
+        private ByteBuffer body;
+        private Exchange camelExchange;
+
+        public UndertowProducerCallback(ByteBuffer body, Exchange camelExchange) {
+            this.body = body;
+            this.camelExchange = camelExchange;
+        }
+
+        @Override
+        public void completed(ClientExchange clientExchange) {
+            clientExchange.setResponseListener(new ClientCallback<ClientExchange>() {
+                @Override
+                public void completed(ClientExchange clientExchange) {
+                    Message message = null;
+                    try {
+                        message = endpoint.getUndertowHttpBinding().toCamelMessage(clientExchange, camelExchange);
+                    } catch (Exception e) {
+                        camelExchange.setException(e);
+                    }
+                    if (ExchangeHelper.isOutCapable(camelExchange)) {
+                        camelExchange.setOut(message);
+                    } else {
+                        camelExchange.setIn(message);
+                    }
+
+                }
+
+                @Override
+                public void failed(IOException e) {
+                    camelExchange.setException(e);
+
+                }
+            });
+            try {
+                //send body if exists
+                if (body != null) {
+                    clientExchange.getRequestChannel().write(body);
+                }
+            } catch (IOException e) {
+                LOG.error("Failed with: " + e.getMessage());
+                camelExchange.setException(e);
+            }
+
+        }
+
+        @Override
+        public void failed(IOException e) {
+            LOG.error("Failed with: " + e.getMessage());
+            camelExchange.setException(e);
+        }
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/100b2f40/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowRegistry.java
----------------------------------------------------------------------
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowRegistry.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowRegistry.java
new file mode 100644
index 0000000..f05adc3
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowRegistry.java
@@ -0,0 +1,116 @@
+/**
+ * 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;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import javax.net.ssl.SSLContext;
+
+import io.undertow.Undertow;
+import org.apache.camel.RuntimeCamelException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class is used to hold Undertow instances during runtime.
+ * One of the benefits is reuse of same TCP port for more endpoints.
+ *
+ */
+public class UndertowRegistry {
+
+    private static final Logger LOG = LoggerFactory.getLogger(UndertowRegistry.class);
+
+    int port;
+    SSLContext sslContext;
+    String host;
+    Undertow server;
+    Map<URI, UndertowConsumer> consumersRegistry = new HashMap<URI, UndertowConsumer>();
+
+    public UndertowRegistry(UndertowConsumer consumer, int port) {
+        registerConsumer(consumer);
+        this.port = port;
+        if (consumer.getEndpoint().getSslContext() != null) {
+            sslContext = consumer.getEndpoint().getSslContext();
+        }
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public void registerConsumer(UndertowConsumer consumer) {
+        URI httpUri = consumer.getEndpoint().getHttpURI();
+        if (host != null && !host.equals(httpUri.getHost())) {
+            throw new RuntimeCamelException("Can't register UndertowConsumer on different host and same port: {}" + host + " " + httpUri.getHost());
+        } else {
+            host = httpUri.getHost();
+        }
+        LOG.info("Adding consumer to consumerRegistry: {}", httpUri);
+        consumersRegistry.put(httpUri, consumer);
+        if (sslContext != null && consumer.getEndpoint().getSslContext() != null) {
+            throw new RuntimeCamelException("Can't register UndertowConsumer with different SSL config");
+        }
+
+    }
+
+    public void unregisterConsumer(UndertowConsumer consumer) {
+        URI httpUri = consumer.getEndpoint().getHttpURI();
+        if (consumersRegistry.containsKey(httpUri)) {
+            consumersRegistry.remove(httpUri);
+        } else {
+            throw new RuntimeCamelException("This consumer is not registered");
+        }
+    }
+
+    public boolean isEmpty() {
+        return consumersRegistry.isEmpty();
+    }
+
+    public Undertow getServer() {
+        return server;
+    }
+
+    public void setServer(Undertow server) {
+        this.server = server;
+    }
+
+    public Map<URI, UndertowConsumer> getConsumersRegistry() {
+        return consumersRegistry;
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public SSLContext getSslContext() {
+        return sslContext;
+    }
+
+    public void setSslContext(SSLContext sslContext) {
+        this.sslContext = sslContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/100b2f40/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowUtils.java
----------------------------------------------------------------------
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowUtils.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowUtils.java
new file mode 100644
index 0000000..188de3b
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowUtils.java
@@ -0,0 +1,49 @@
+/**
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Util class for useful methods used all over the component
+ *
+ */
+public final class UndertowUtils {
+
+    private UndertowUtils() {
+    }
+
+    public static void appendHeader(Map<String, Object> headers, String key, Object value) {
+        if (headers.containsKey(key)) {
+            Object existing = headers.get(key);
+            List<Object> list;
+            if (existing instanceof List) {
+                list = (List<Object>) existing;
+            } else {
+                list = new ArrayList<Object>();
+                list.add(existing);
+            }
+            list.add(value);
+            value = list;
+        }
+
+        headers.put(key, value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/100b2f40/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/HttpCamelHandler.java
----------------------------------------------------------------------
diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/HttpCamelHandler.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/HttpCamelHandler.java
new file mode 100644
index 0000000..3900dd3
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/HttpCamelHandler.java
@@ -0,0 +1,132 @@
+/**
+ * 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.nio.ByteBuffer;
+
+import io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.util.Headers;
+import io.undertow.util.HttpString;
+import io.undertow.util.Methods;
+import io.undertow.util.MimeMappings;
+import io.undertow.util.StatusCodes;
+import org.apache.camel.Exchange;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.component.undertow.ExchangeHeaders;
+import org.apache.camel.component.undertow.UndertowConsumer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Custom handler to process incoming HTTP request and prepare them
+ * to be used in the Camel route.
+ *
+ * This class can be considered part of UndertowConsumer implementation.
+ *
+ */
+public class HttpCamelHandler implements HttpHandler {
+    private static final Logger LOG = LoggerFactory.getLogger(UndertowConsumer.class);
+
+    private UndertowConsumer consumer;
+
+    public HttpCamelHandler(UndertowConsumer consumer) {
+        this.consumer = consumer;
+    }
+
+    public UndertowConsumer getConsumer() {
+        return consumer;
+    }
+
+    @Override
+    public void handleRequest(HttpServerExchange httpExchange) throws Exception {
+        HttpString requestMethod = httpExchange.getRequestMethod();
+
+        if (Methods.OPTIONS.equals(requestMethod)) {
+            String allowedMethods;
+            if (consumer.getEndpoint().getHttpMethodRestrict() != null) {
+                allowedMethods = "OPTIONS" + consumer.getEndpoint().getHttpMethodRestrict();
+            } else {
+                allowedMethods = "GET,HEAD,POST,PUT,DELETE,TRACE,OPTIONS,CONNECT,PATCH";
+            }
+            //return list of allowed methods in response headers
+            httpExchange.setResponseCode(StatusCodes.OK);
+            httpExchange.getResponseHeaders().put(ExchangeHeaders.CONTENT_TYPE, MimeMappings.DEFAULT_MIME_MAPPINGS.get("txt"));
+            httpExchange.getResponseHeaders().put(ExchangeHeaders.CONTENT_LENGTH, 0);
+            httpExchange.getResponseHeaders().put(Headers.ALLOW, allowedMethods);
+            httpExchange.getResponseSender().close();
+            return;
+        }
+
+        //reject if the method is not allowed
+        if (consumer.getEndpoint().getHttpMethodRestrict() != null
+            && !consumer.getEndpoint().getHttpMethodRestrict().contains(requestMethod.toString())) {
+            httpExchange.setResponseCode(StatusCodes.METHOD_NOT_ALLOWED);
+            httpExchange.getResponseHeaders().put(ExchangeHeaders.CONTENT_TYPE, MimeMappings.DEFAULT_MIME_MAPPINGS.get("txt"));
+            httpExchange.getResponseHeaders().put(ExchangeHeaders.CONTENT_LENGTH, 0);
+            httpExchange.getResponseSender().close();
+            return;
+        }
+
+        //perform blocking operation on exchange
+        if (httpExchange.isInIoThread()) {
+            httpExchange.dispatch(this);
+            return;
+        }
+
+        //create new Exchange
+        //binding is used to extract header and payload(if available)
+        Exchange camelExchange = consumer.getEndpoint().createExchange(httpExchange);
+
+        //Unit of Work to process the Exchange
+        consumer.createUoW(camelExchange);
+        try {
+            consumer.getProcessor().process(camelExchange);
+        } catch (Exception e) {
+            consumer.getExceptionHandler().handleException(e);
+        } finally {
+            consumer.doneUoW(camelExchange);
+        }
+
+        Object body = getResponseBody(httpExchange, camelExchange);
+        TypeConverter tc = consumer.getEndpoint().getCamelContext().getTypeConverter();
+
+        if (body == null) {
+            LOG.trace("No payload to send as reply for exchange: " + camelExchange);
+            httpExchange.getResponseHeaders().put(ExchangeHeaders.CONTENT_TYPE, MimeMappings.DEFAULT_MIME_MAPPINGS.get("txt"));
+            httpExchange.getResponseSender().send("No response available");
+        } else {
+            ByteBuffer bodyAsByteBuffer = tc.convertTo(ByteBuffer.class, body);
+            httpExchange.getResponseSender().send(bodyAsByteBuffer);
+        }
+        httpExchange.getResponseSender().close();
+    }
+
+
+    private Object getResponseBody(HttpServerExchange httpExchange, Exchange camelExchange) {
+        Object result;
+        if (camelExchange.hasOut()) {
+            result = consumer.getEndpoint().getUndertowHttpBinding().toHttpResponse(httpExchange, camelExchange.getOut());
+        } else {
+            result = consumer.getEndpoint().getUndertowHttpBinding().toHttpResponse(httpExchange, camelExchange.getIn());
+        }
+        return result;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/100b2f40/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/NotFoundHandler.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..932380c
--- /dev/null
+++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/handlers/NotFoundHandler.java
@@ -0,0 +1,36 @@
+/**
+ * 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 io.undertow.server.HttpHandler;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.util.Headers;
+
+/**
+ * Custom handler to inform client that no matching path was found
+ *
+ */
+public class NotFoundHandler implements HttpHandler {
+
+    @Override
+    public void handleRequest(HttpServerExchange exchange) throws Exception {
+        exchange.setResponseCode(404);
+        exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
+        exchange.getResponseSender().send("No matching path found");
+    }
+}