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 2016/03/04 10:45:36 UTC

[1/2] camel git commit: CAMEL-9660 - HTTP producers crash when Exchange.HTTP_URI header contains unencoded unsafe characters

Repository: camel
Updated Branches:
  refs/heads/camel-2.16.x ac83e1023 -> 8f11babb7


CAMEL-9660 - HTTP producers crash when Exchange.HTTP_URI header contains unencoded unsafe characters


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

Branch: refs/heads/camel-2.16.x
Commit: 5d84ac78777974de44b4a338483e201e3501f876
Parents: ac83e10
Author: Tadayoshi Sato <sa...@gmail.com>
Authored: Wed Mar 2 15:26:46 2016 +0900
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Mar 4 10:44:39 2016 +0100

----------------------------------------------------------------------
 .../apache/camel/http/common/HttpHelper.java    |  2 +
 .../component/http/HttpBridgeEndpointTest.java  | 13 ++++++
 .../http4/helper/HttpMethodHelper.java          |  7 ++-
 .../component/http4/HttpBridgeEndpointTest.java | 14 ++++++
 .../jetty/HttpProducerUnsafeCharsTest.java      | 47 ++++++++++++++++++++
 5 files changed, 79 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/5d84ac78/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpHelper.java b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpHelper.java
index 08f2e2d..9749b97 100644
--- a/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpHelper.java
+++ b/components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpHelper.java
@@ -497,6 +497,8 @@ public final class HttpHelper {
             throw new RuntimeExchangeException("Cannot resolve property placeholders with uri: " + uriString, exchange, e);
         }
         if (uriString != null) {
+            // in case the URI string contains unsafe characters
+            uriString = UnsafeUriCharactersEncoder.encodeHttpURI(uriString);
             URI uri = new URI(uriString);
             queryString = uri.getQuery();
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/5d84ac78/components/camel-http/src/test/java/org/apache/camel/component/http/HttpBridgeEndpointTest.java
----------------------------------------------------------------------
diff --git a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpBridgeEndpointTest.java b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpBridgeEndpointTest.java
index 3e021e9..02484df 100644
--- a/components/camel-http/src/test/java/org/apache/camel/component/http/HttpBridgeEndpointTest.java
+++ b/components/camel-http/src/test/java/org/apache/camel/component/http/HttpBridgeEndpointTest.java
@@ -106,4 +106,17 @@ public class HttpBridgeEndpointTest extends BaseHttpTest {
         assertExchange(exchange);
     }
 
+    @Test
+    public void unsafeCharsInHttpURIHeader() throws Exception {
+        Exchange exchange = template.request("http://localhost:" + PORT + "/?bridgeEndpoint=true", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(Exchange.HTTP_URI, "/<>{}");
+            }
+        });
+
+        assertNull(exchange.getException());
+        assertExchange(exchange);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/5d84ac78/components/camel-http4/src/main/java/org/apache/camel/component/http4/helper/HttpMethodHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-http4/src/main/java/org/apache/camel/component/http4/helper/HttpMethodHelper.java b/components/camel-http4/src/main/java/org/apache/camel/component/http4/helper/HttpMethodHelper.java
index ddf408f..57c4c9d 100644
--- a/components/camel-http4/src/main/java/org/apache/camel/component/http4/helper/HttpMethodHelper.java
+++ b/components/camel-http4/src/main/java/org/apache/camel/component/http4/helper/HttpMethodHelper.java
@@ -23,13 +23,10 @@ import org.apache.camel.Exchange;
 import org.apache.camel.RuntimeExchangeException;
 import org.apache.camel.component.http4.HttpEndpoint;
 import org.apache.camel.component.http4.HttpMethods;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.camel.util.UnsafeUriCharactersEncoder;
 
 public final class HttpMethodHelper {
 
-    private static final Logger LOG = LoggerFactory.getLogger(HttpMethodHelper.class);
-
     private HttpMethodHelper() {
         // Helper class
     }
@@ -54,6 +51,8 @@ public final class HttpMethodHelper {
             throw new RuntimeExchangeException("Cannot resolve property placeholders with uri: " + uriString, exchange, e);
         }
         if (uriString != null) {
+            // in case the URI string contains unsafe characters
+            uriString = UnsafeUriCharactersEncoder.encodeHttpURI(uriString);
             URI uri = new URI(uriString);
             queryString = uri.getQuery();
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/5d84ac78/components/camel-http4/src/test/java/org/apache/camel/component/http4/HttpBridgeEndpointTest.java
----------------------------------------------------------------------
diff --git a/components/camel-http4/src/test/java/org/apache/camel/component/http4/HttpBridgeEndpointTest.java b/components/camel-http4/src/test/java/org/apache/camel/component/http4/HttpBridgeEndpointTest.java
index 5ecb67f..50f22c5 100644
--- a/components/camel-http4/src/test/java/org/apache/camel/component/http4/HttpBridgeEndpointTest.java
+++ b/components/camel-http4/src/test/java/org/apache/camel/component/http4/HttpBridgeEndpointTest.java
@@ -106,4 +106,18 @@ public class HttpBridgeEndpointTest extends BaseHttpTest {
 
         assertExchange(exchange);
     }
+
+    @Test
+    public void unsafeCharsInHttpURIHeader() throws Exception {
+        Exchange exchange = template.request("http4://" + localServer.getInetAddress().getHostName() + ":" + localServer.getLocalPort() + "/?bridgeEndpoint=true", new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(Exchange.HTTP_URI, "/<>{}");
+            }
+        });
+
+        assertNull(exchange.getException());
+        assertExchange(exchange);
+    }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/5d84ac78/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/HttpProducerUnsafeCharsTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/HttpProducerUnsafeCharsTest.java b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/HttpProducerUnsafeCharsTest.java
new file mode 100644
index 0000000..7e46bea
--- /dev/null
+++ b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/HttpProducerUnsafeCharsTest.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.jetty;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.Test;
+
+public class HttpProducerUnsafeCharsTest extends BaseJettyTest {
+
+    @Test
+    public void unsafeCharsInHttpURIHeader() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+
+        template.sendBodyAndHeader("jetty:http://localhost:{{port}}/test?bridgeEndpoint=true", "Hello World",
+                Exchange.HTTP_URI, "/<>{}");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("jetty:http://localhost:{{port}}/test").to("mock:result");
+            }
+        };
+    }
+
+}


[2/2] camel git commit: CAMEL-9658 - Path gets decoded when bridging HTTP endpoints

Posted by da...@apache.org.
CAMEL-9658 - Path gets decoded when bridging HTTP endpoints


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

Branch: refs/heads/camel-2.16.x
Commit: 8f11babb72927f2b88e3c87b1b81d1acc621b29a
Parents: 5d84ac7
Author: Tadayoshi Sato <sa...@gmail.com>
Authored: Tue Mar 1 22:04:59 2016 +0900
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Mar 4 10:44:47 2016 +0100

----------------------------------------------------------------------
 .../camel/http/common/DefaultHttpBinding.java   | 14 ++++++--
 .../jetty/CamelContinuationServlet.java         | 22 +++++++-----
 .../jetty/HttpBridgeEncodedPathTest.java        | 37 +++++++++++++++++---
 .../netty/http/DefaultNettyHttpBinding.java     |  2 +-
 .../http/NettyHttpBridgeEncodedPathTest.java    | 36 +++++++++++++++++--
 .../netty4/http/DefaultNettyHttpBinding.java    |  2 +-
 .../http/NettyHttpBridgeEncodedPathTest.java    | 36 +++++++++++++++++--
 7 files changed, 128 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/8f11babb/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
----------------------------------------------------------------------
diff --git a/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java b/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
index 04f5851..ad9adfe 100644
--- a/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
+++ b/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
@@ -137,11 +137,12 @@ public class DefaultHttpBinding implements HttpBinding {
         }
 
         // store the method and query and other info in headers as String types
+        String rawPath = getRawPath(request);
         headers.put(Exchange.HTTP_METHOD, request.getMethod());
         headers.put(Exchange.HTTP_QUERY, request.getQueryString());
         headers.put(Exchange.HTTP_URL, request.getRequestURL().toString());
         headers.put(Exchange.HTTP_URI, request.getRequestURI());
-        headers.put(Exchange.HTTP_PATH, request.getPathInfo());
+        headers.put(Exchange.HTTP_PATH, rawPath);
         headers.put(Exchange.CONTENT_TYPE, request.getContentType());
 
         if (LOG.isTraceEnabled()) {
@@ -149,7 +150,7 @@ public class DefaultHttpBinding implements HttpBinding {
             LOG.trace("HTTP query {}", request.getQueryString());
             LOG.trace("HTTP url {}", request.getRequestURL());
             LOG.trace("HTTP uri {}", request.getRequestURI());
-            LOG.trace("HTTP path {}", request.getPathInfo());
+            LOG.trace("HTTP path {}", rawPath);
             LOG.trace("HTTP content-type {}", request.getContentType());
         }
 
@@ -224,7 +225,14 @@ public class DefaultHttpBinding implements HttpBinding {
             }
         }
     }
-    
+
+    private String getRawPath(HttpServletRequest request) {
+        String uri = request.getRequestURI();
+        String contextPath = request.getContextPath();
+        String servletPath = request.getServletPath();
+        return uri.substring(contextPath.length() + servletPath.length());
+    }
+
     protected void populateAttachments(HttpServletRequest request, HttpMessage message) {
         // check if there is multipart files, if so will put it into DataHandler
         Enumeration<?> names = request.getAttributeNames();

http://git-wip-us.apache.org/repos/asf/camel/blob/8f11babb/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java
----------------------------------------------------------------------
diff --git a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java
index a6a2e9c..9e77b29 100644
--- a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java
+++ b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java
@@ -35,6 +35,7 @@ import org.apache.camel.http.common.HttpHelper;
 import org.apache.camel.http.common.HttpMessage;
 import org.apache.camel.impl.DefaultExchange;
 import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.UnsafeUriCharactersEncoder;
 import org.eclipse.jetty.continuation.Continuation;
 import org.eclipse.jetty.continuation.ContinuationSupport;
 
@@ -161,14 +162,8 @@ public class CamelContinuationServlet extends CamelServlet {
             // set context path as header
             String contextPath = consumer.getEndpoint().getPath();
             exchange.getIn().setHeader("CamelServletContextPath", contextPath);
-            
-            String httpPath = (String)exchange.getIn().getHeader(Exchange.HTTP_PATH);
-            // here we just remove the CamelServletContextPath part from the HTTP_PATH
-            if (contextPath != null
-                && httpPath.startsWith(contextPath)) {
-                exchange.getIn().setHeader(Exchange.HTTP_PATH,
-                        httpPath.substring(contextPath.length()));
-            }
+
+            updateHttpPath(exchange, contextPath);
 
             if (log.isTraceEnabled()) {
                 log.trace("Suspending continuation of exchangeId: {}", exchange.getExchangeId());
@@ -241,6 +236,17 @@ public class CamelContinuationServlet extends CamelServlet {
         }
     }
 
+    private void updateHttpPath(Exchange exchange, String contextPath) {
+        String httpPath = (String) exchange.getIn().getHeader(Exchange.HTTP_PATH);
+        // encode context path in case it contains unsafe chars, because HTTP_PATH isn't decoded at this moment
+        String encodedContextPath = UnsafeUriCharactersEncoder.encodeHttpURI(contextPath);
+
+        // here we just remove the CamelServletContextPath part from the HTTP_PATH
+        if (contextPath != null && httpPath.startsWith(encodedContextPath)) {
+            exchange.getIn().setHeader(Exchange.HTTP_PATH, httpPath.substring(encodedContextPath.length()));
+        }
+    }
+
     @Override
     public void destroy() {
         expiredExchanges.clear();

http://git-wip-us.apache.org/repos/asf/camel/blob/8f11babb/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/HttpBridgeEncodedPathTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/HttpBridgeEncodedPathTest.java b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/HttpBridgeEncodedPathTest.java
index d1e3410..2ad8ca8 100644
--- a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/HttpBridgeEncodedPathTest.java
+++ b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/HttpBridgeEncodedPathTest.java
@@ -17,29 +17,55 @@
 package org.apache.camel.component.jetty;
 
 import java.io.ByteArrayInputStream;
+import java.net.URLEncoder;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.GetMethod;
 import org.junit.Test;
 
 public class HttpBridgeEncodedPathTest extends BaseJettyTest {
 
     private int port1;
     private int port2;
+    private int port3;
+    private int port4;
 
     @Test
-    public void testHttpClient() throws Exception {
+    public void testEncodedQuery() throws Exception {
         String response = template.requestBodyAndHeader("http://localhost:" + port2 + "/test/hello?param1=%2B447777111222",
                 new ByteArrayInputStream("This is a test".getBytes()), "Content-Type", "text/plain", String.class);
         assertEquals("Get a wrong response", "param1=+447777111222", response);
     }
 
+    @Test
+    public void testEncodedPath() throws Exception {
+        String path = URLEncoder.encode(" :/?#[]@!$", "UTF-8") + "/" + URLEncoder.encode("&'()+,;=", "UTF-8");
+        MockEndpoint mock = getMockEndpoint("mock:encodedPath");
+        mock.message(0).header(Exchange.HTTP_URI).isEqualTo("/" + path);
+        mock.message(0).header(Exchange.HTTP_PATH).isEqualTo(path);
+        mock.message(0).header(Exchange.HTTP_QUERY).isNull();
+        mock.message(0).header(Exchange.HTTP_RAW_QUERY).isNull();
+
+        // cannot use template as it automatically decodes some chars in the path
+        HttpClient httpClient = new HttpClient();
+        GetMethod httpGet = new GetMethod("http://localhost:" + port4 + "/test/" + path);
+        int status = httpClient.executeMethod(httpGet);
+
+        assertEquals("Get a wrong response status", 200, status);
+        assertMockEndpointsSatisfied();
+    }
+
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
             public void configure() {
                 port1 = getPort();
-                port2 = getNextPort();
+                port2 = getPort2();
+                port3 = getNextPort();
+                port4 = getNextPort();
 
                 errorHandler(noErrorHandler());
 
@@ -56,8 +82,11 @@ public class HttpBridgeEncodedPathTest extends BaseJettyTest {
                 };
                 from("jetty:http://localhost:" + port2 + "/test/hello")
                     .to("http://localhost:" + port1 + "?throwExceptionOnFailure=false&bridgeEndpoint=true");
-                
-                from("jetty://http://localhost:" + port1 + "?matchOnUriPrefix=true").process(serviceProc);
+                from("jetty:http://localhost:" + port1 + "?matchOnUriPrefix=true").process(serviceProc);
+
+                from("jetty:http://localhost:" + port4 + "/test?matchOnUriPrefix=true")
+                    .to("http://localhost:" + port3 + "?throwExceptionOnFailure=false&bridgeEndpoint=true");
+                from("jetty:http://localhost:" + port3 + "?matchOnUriPrefix=true").to("mock:encodedPath");
             }
         };
     }    

http://git-wip-us.apache.org/repos/asf/camel/blob/8f11babb/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultNettyHttpBinding.java
----------------------------------------------------------------------
diff --git a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultNettyHttpBinding.java b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultNettyHttpBinding.java
index 05bd551..192d4c1 100644
--- a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultNettyHttpBinding.java
+++ b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultNettyHttpBinding.java
@@ -132,7 +132,7 @@ public class DefaultNettyHttpBinding implements NettyHttpBinding, Cloneable {
         headers.put(Exchange.HTTP_RAW_QUERY, uri.getRawQuery());
 
         // strip the starting endpoint path so the path is relative to the endpoint uri
-        String path = uri.getPath();
+        String path = uri.getRawPath();
         if (configuration.getPath() != null) {
             // need to match by lower case as we want to ignore case on context-path
             String matchPath = path.toLowerCase(Locale.US);

http://git-wip-us.apache.org/repos/asf/camel/blob/8f11babb/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpBridgeEncodedPathTest.java
----------------------------------------------------------------------
diff --git a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpBridgeEncodedPathTest.java b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpBridgeEncodedPathTest.java
index 25a3bff..4c51795 100644
--- a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpBridgeEncodedPathTest.java
+++ b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpBridgeEncodedPathTest.java
@@ -16,28 +16,54 @@
  */
 package org.apache.camel.component.netty.http;
 
+import java.net.URLEncoder;
+
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.GetMethod;
 import org.junit.Test;
 
 public class NettyHttpBridgeEncodedPathTest extends BaseNettyTest {
 
     private int port1;
     private int port2;
+    private int port3;
+    private int port4;
 
     @Test
-    public void testHttpClient() throws Exception {
+    public void testEncodedQuery() throws Exception {
         String response = template.requestBody("http://localhost:" + port2 + "/nettyTestRouteA?param1=%2B447777111222", null, String.class);
         assertEquals("Get a wrong response", "param1=+447777111222", response);
     }
 
+    @Test
+    public void testEncodedPath() throws Exception {
+        String path = URLEncoder.encode(" :/?#[]@!$", "UTF-8") + "/" + URLEncoder.encode("&'()+,;=", "UTF-8");
+        MockEndpoint mock = getMockEndpoint("mock:encodedPath");
+        mock.message(0).header(Exchange.HTTP_PATH).isEqualTo("/" + path);
+        mock.message(0).header(Exchange.HTTP_QUERY).isNull();
+        mock.message(0).header(Exchange.HTTP_RAW_QUERY).isNull();
+
+        // cannot use template as it automatically decodes some chars in the path
+        HttpClient httpClient = new HttpClient();
+        GetMethod httpGet = new GetMethod("http://localhost:" + port4 + "/nettyTestRouteC/" + path);
+        int status = httpClient.executeMethod(httpGet);
+
+        assertEquals("Get a wrong response status", 200, status);
+        assertMockEndpointsSatisfied();
+    }
+
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
             public void configure() {
 
                 port1 = getPort();
                 port2 = getNextPort();
+                port3 = getNextPort();
+                port4 = getNextPort();
 
                 errorHandler(noErrorHandler());
 
@@ -55,10 +81,16 @@ public class NettyHttpBridgeEncodedPathTest extends BaseNettyTest {
                 from("netty-http:http://localhost:" + port2 + "/nettyTestRouteA?matchOnUriPrefix=true")
                         .log("Using NettyTestRouteA route: CamelHttpPath=[${header.CamelHttpPath}], CamelHttpUri=[${header.CamelHttpUri}]")
                         .to("netty-http:http://localhost:" + port1 + "/nettyTestRouteB?throwExceptionOnFailure=false&bridgeEndpoint=true");
-
                 from("netty-http:http://localhost:" + port1 + "/nettyTestRouteB?matchOnUriPrefix=true")
                         .log("Using NettyTestRouteB route: CamelHttpPath=[${header.CamelHttpPath}], CamelHttpUri=[${header.CamelHttpUri}]")
                         .process(serviceProc);
+
+                from("netty-http:http://localhost:" + port4 + "/nettyTestRouteC?matchOnUriPrefix=true")
+                        .log("Using NettyTestRouteC route: CamelHttpPath=[${header.CamelHttpPath}], CamelHttpUri=[${header.CamelHttpUri}]")
+                        .to("netty-http:http://localhost:" + port3 + "/nettyTestRouteD?throwExceptionOnFailure=false&bridgeEndpoint=true");
+                from("netty-http:http://localhost:" + port3 + "/nettyTestRouteD?matchOnUriPrefix=true")
+                        .log("Using NettyTestRouteD route: CamelHttpPath=[${header.CamelHttpPath}], CamelHttpUri=[${header.CamelHttpUri}]")
+                        .to("mock:encodedPath");
             }
         };
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/8f11babb/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/DefaultNettyHttpBinding.java
----------------------------------------------------------------------
diff --git a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/DefaultNettyHttpBinding.java b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/DefaultNettyHttpBinding.java
index 0a183a3..552f5de 100644
--- a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/DefaultNettyHttpBinding.java
+++ b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/DefaultNettyHttpBinding.java
@@ -134,7 +134,7 @@ public class DefaultNettyHttpBinding implements NettyHttpBinding, Cloneable {
         headers.put(Exchange.HTTP_RAW_QUERY, uri.getRawQuery());
 
         // strip the starting endpoint path so the path is relative to the endpoint uri
-        String path = uri.getPath();
+        String path = uri.getRawPath();
         if (configuration.getPath() != null) {
             // need to match by lower case as we want to ignore case on context-path
             String matchPath = path.toLowerCase(Locale.US);

http://git-wip-us.apache.org/repos/asf/camel/blob/8f11babb/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttpBridgeEncodedPathTest.java
----------------------------------------------------------------------
diff --git a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttpBridgeEncodedPathTest.java b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttpBridgeEncodedPathTest.java
index a2c9b3c..76d02ee 100644
--- a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttpBridgeEncodedPathTest.java
+++ b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/NettyHttpBridgeEncodedPathTest.java
@@ -16,28 +16,54 @@
  */
 package org.apache.camel.component.netty4.http;
 
+import java.net.URLEncoder;
+
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.GetMethod;
 import org.junit.Test;
 
 public class NettyHttpBridgeEncodedPathTest extends BaseNettyTest {
 
     private int port1;
     private int port2;
+    private int port3;
+    private int port4;
 
     @Test
-    public void testHttpClient() throws Exception {
+    public void testEncodedQuery() throws Exception {
         String response = template.requestBody("http://localhost:" + port2 + "/nettyTestRouteA?param1=%2B447777111222", null, String.class);
         assertEquals("Get a wrong response", "param1=+447777111222", response);
     }
 
+    @Test
+    public void testEncodedPath() throws Exception {
+        String path = URLEncoder.encode(" :/?#[]@!$", "UTF-8") + "/" + URLEncoder.encode("&'()+,;=", "UTF-8");
+        MockEndpoint mock = getMockEndpoint("mock:encodedPath");
+        mock.message(0).header(Exchange.HTTP_PATH).isEqualTo("/" + path);
+        mock.message(0).header(Exchange.HTTP_QUERY).isNull();
+        mock.message(0).header(Exchange.HTTP_RAW_QUERY).isNull();
+
+        // cannot use template as it automatically decodes some chars in the path
+        HttpClient httpClient = new HttpClient();
+        GetMethod httpGet = new GetMethod("http://localhost:" + port4 + "/nettyTestRouteC/" + path);
+        int status = httpClient.executeMethod(httpGet);
+
+        assertEquals("Get a wrong response status", 200, status);
+        assertMockEndpointsSatisfied();
+    }
+
     protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
             public void configure() {
 
                 port1 = getPort();
                 port2 = getNextPort();
+                port3 = getNextPort();
+                port4 = getNextPort();
 
                 errorHandler(noErrorHandler());
 
@@ -55,10 +81,16 @@ public class NettyHttpBridgeEncodedPathTest extends BaseNettyTest {
                 from("netty4-http:http://localhost:" + port2 + "/nettyTestRouteA?matchOnUriPrefix=true")
                         .log("Using NettyTestRouteA route: CamelHttpPath=[${header.CamelHttpPath}], CamelHttpUri=[${header.CamelHttpUri}]")
                         .to("netty4-http:http://localhost:" + port1 + "/nettyTestRouteB?throwExceptionOnFailure=false&bridgeEndpoint=true");
-
                 from("netty4-http:http://localhost:" + port1 + "/nettyTestRouteB?matchOnUriPrefix=true")
                         .log("Using NettyTestRouteB route: CamelHttpPath=[${header.CamelHttpPath}], CamelHttpUri=[${header.CamelHttpUri}]")
                         .process(serviceProc);
+
+                from("netty4-http:http://localhost:" + port4 + "/nettyTestRouteC?matchOnUriPrefix=true")
+                        .log("Using NettyTestRouteC route: CamelHttpPath=[${header.CamelHttpPath}], CamelHttpUri=[${header.CamelHttpUri}]")
+                        .to("netty4-http:http://localhost:" + port3 + "/nettyTestRouteD?throwExceptionOnFailure=false&bridgeEndpoint=true");
+                from("netty4-http:http://localhost:" + port3 + "/nettyTestRouteD?matchOnUriPrefix=true")
+                        .log("Using NettyTestRouteD route: CamelHttpPath=[${header.CamelHttpPath}], CamelHttpUri=[${header.CamelHttpUri}]")
+                        .to("mock:encodedPath");
             }
         };
     }