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

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


The following commit(s) were added to refs/heads/master by this push:
     new c33950c  CAMEL-13521: Add reverse proxy option in camel-...
c33950c is described below

commit c33950c8a4627aacc9d7c22621847583c12b4014
Author: Zoran Regvart <zregv...@apache.org>
AuthorDate: Mon May 13 12:29:22 2019 +0200

    CAMEL-13521: Add reverse proxy option in camel-...
    
    ...netty4-http
    
    This adds support for reverse proxy functionality in `camel-netty4-http`
    component.
---
 components/camel-netty4-http/pom.xml               |  5 ++
 .../src/main/docs/netty4-http-component.adoc       | 37 +++++++++-
 .../netty4/http/DefaultNettyHttpBinding.java       | 56 +++++++++++----
 .../component/netty4/http/NettyHttpComponent.java  | 24 ++++---
 .../netty4/http/NettyHttpConfiguration.java        |  6 +-
 .../http/handlers/HttpServerChannelHandler.java    | 11 ++-
 .../HttpServerMultiplexChannelHandler.java         | 12 ++++
 .../component/netty4/http/ProxyProtocolTest.java   | 84 ++++++++++++++++++++++
 .../src/main/java/org/apache/camel/Exchange.java   |  5 +-
 .../NettyHttpComponentConfiguration.java           |  3 +-
 10 files changed, 215 insertions(+), 28 deletions(-)

diff --git a/components/camel-netty4-http/pom.xml 
b/components/camel-netty4-http/pom.xml
index dd08d5b..f381f0a 100644
--- a/components/camel-netty4-http/pom.xml
+++ b/components/camel-netty4-http/pom.xml
@@ -82,6 +82,11 @@
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
         <!-- for testing rest-dsl -->
         <dependency>
             <groupId>org.apache.camel</groupId>
diff --git 
a/components/camel-netty4-http/src/main/docs/netty4-http-component.adoc 
b/components/camel-netty4-http/src/main/docs/netty4-http-component.adoc
index 91790d7..e2de392 100644
--- a/components/camel-netty4-http/src/main/docs/netty4-http-component.adoc
+++ b/components/camel-netty4-http/src/main/docs/netty4-http-component.adoc
@@ -131,7 +131,7 @@ with the following path and query parameters:
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
 | Name | Description | Default | Type
-| *protocol* | *Required* The protocol to use which is either http or https |  
| String
+| *protocol* | *Required* The protocol to use which is either http, https or 
proxy - a consumer only option. |  | String
 | *host* | *Required* The local hostname such as localhost, or 0.0.0.0 when 
being a consumer. The remote HTTP server hostname when using producer. |  | 
String
 | *port* | The host port number |  | int
 | *path* | Resource path |  | String
@@ -391,7 +391,7 @@ ProducerTemplate as shown below:
 
 And we get back "Bye World" as the output.
 
-=== How do I let Netty match wildcards
+==== How do I let Netty match wildcards
 
 By default Netty4 HTTP will only match on exact uri's. But you can
 instruct Netty to match prefixes. For example
@@ -422,7 +422,7 @@ To match *any* endpoint you can do:
 from("netty4-http:http://0.0.0.0:8123?matchOnUriPrefix=true";).to("mock:foo");
 -----------------------------------------------------------------------------
 
-=== Using multiple routes with same port
+==== Using multiple routes with same port
 
 In the same CamelContext you can have multiple
 routes from Netty4 HTTP that shares the same port (eg a
@@ -517,6 +517,37 @@ And in the routes you refer to this option as shown below
 See the Netty HTTP Server Example
 for more details and example how to do that.
 
+==== Implementing a reverse proxy
+
+Netty HTTP component can act as a reverse proxy, in that case
+`Exchange.HTTP_SCHEME`, `Exchange.HTTP_HOST` and
+`Exchange.HTTP_PORT` headers are populated from the absolute
+URL received on the request line of the HTTP request.
+
+Here's an example of a HTTP proxy that simply transforms the response
+from the origin server to uppercase.
+
+[source,java]
+------------------------------------------------------------------------------------------
+from("netty-http:proxy://0.0.0.0:8080")
+    .toD("netty-http:"
+        + "${headers." + Exchange.HTTP_SCHEME + "}://"
+        + "${headers." + Exchange.HTTP_HOST + "}:"
+        + "${headers." + Exchange.HTTP_PORT + "}")
+    .process(this::processResponse);
+
+void processResponse(final Exchange exchange) {
+    final NettyHttpMessage message = exchange.getIn(NettyHttpMessage.class);
+    final FullHttpResponse response = message.getHttpResponse();
+
+    final ByteBuf buf = response.content();
+    final String string = buf.toString(StandardCharsets.UTF_8);
+
+    buf.resetWriterIndex();
+    ByteBufUtil.writeUtf8(buf, string.toUpperCase(Locale.US));
+}
+------------------------------------------------------------------------------------------
+
 === Using HTTP Basic Authentication
 
 The Netty HTTP consumer supports HTTP basic authentication by specifying
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 630eae1..a626c0e 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
@@ -41,9 +41,9 @@ import io.netty.handler.codec.http.HttpRequest;
 import io.netty.handler.codec.http.HttpResponse;
 import io.netty.handler.codec.http.HttpResponseStatus;
 import io.netty.handler.codec.http.HttpVersion;
+
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
-import org.apache.camel.NoTypeConversionAvailableException;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.TypeConverter;
 import org.apache.camel.component.netty4.NettyConstants;
@@ -91,8 +91,9 @@ public class DefaultNettyHttpBinding implements 
NettyHttpBinding, Cloneable {
             populateCamelHeaders(request, answer.getHeaders(), exchange, 
configuration);
         }
 
-        if (configuration.isDisableStreamCache()) {
+        if (configuration.isHttpProxy() || 
configuration.isDisableStreamCache()) {
             // keep the body as is, and use type converters
+            // for proxy use case pass the request body buffer directly to the 
response to avoid additional processing
             answer.setBody(request.content());
         } else {
             // turn the body into stream cached (on the client/consumer side 
we can facade the netty stream instead of converting to byte array)
@@ -136,6 +137,10 @@ public class DefaultNettyHttpBinding implements 
NettyHttpBinding, Cloneable {
         headers.put(Exchange.HTTP_URI, uri.getPath());
         headers.put(Exchange.HTTP_QUERY, uri.getQuery());
         headers.put(Exchange.HTTP_RAW_QUERY, uri.getRawQuery());
+        headers.put(Exchange.HTTP_SCHEME, uri.getScheme());
+        headers.put(Exchange.HTTP_HOST, uri.getHost());
+        final int port = uri.getPort();
+        headers.put(Exchange.HTTP_PORT, port > 0 ? port : 80);
 
         // strip the starting endpoint path so the path is relative to the 
endpoint uri
         String path = uri.getRawPath();
@@ -270,7 +275,7 @@ public class DefaultNettyHttpBinding implements 
NettyHttpBinding, Cloneable {
             populateCamelHeaders(response, answer.getHeaders(), exchange, 
configuration);
         }
 
-        if (configuration.isDisableStreamCache()) {
+        if (configuration.isDisableStreamCache() || 
configuration.isHttpProxy()) {
             // keep the body as is, and use type converters
             answer.setBody(response.content());
         } else {
@@ -316,6 +321,15 @@ public class DefaultNettyHttpBinding implements 
NettyHttpBinding, Cloneable {
     public HttpResponse toNettyResponse(Message message, 
NettyHttpConfiguration configuration) throws Exception {
         LOG.trace("toNettyResponse: {}", message);
 
+        if (message instanceof NettyHttpMessage) {
+            final NettyHttpMessage nettyHttpMessage = (NettyHttpMessage) 
message;
+            final FullHttpResponse response = 
nettyHttpMessage.getHttpResponse();
+
+            if (response != null) {
+                return response.retain();
+            }
+        }
+
         // the message body may already be a Netty HTTP response
         if (message.getBody() instanceof HttpResponse) {
             return (HttpResponse) message.getBody();
@@ -459,8 +473,9 @@ public class DefaultNettyHttpBinding implements 
NettyHttpBinding, Cloneable {
     public HttpRequest toNettyRequest(Message message, String fullUri, 
NettyHttpConfiguration configuration) throws Exception {
         LOG.trace("toNettyRequest: {}", message);
 
+        Object body = message.getBody();
         // the message body may already be a Netty HTTP response
-        if (message.getBody() instanceof HttpRequest) {
+        if (body instanceof HttpRequest) {
             return (HttpRequest) message.getBody();
         }
 
@@ -477,10 +492,24 @@ public class DefaultNettyHttpBinding implements 
NettyHttpBinding, Cloneable {
             }
         }
 
-        // just assume GET for now, we will later change that to the actual 
method to use
-        HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, 
HttpMethod.GET, uriForRequest);
+        final String headerProtocolVersion = 
message.getHeader(Exchange.HTTP_PROTOCOL_VERSION, String.class);
+        final HttpVersion protocol;
+        if (headerProtocolVersion == null) {
+            protocol = HttpVersion.HTTP_1_1;
+        } else {
+            protocol = HttpVersion.valueOf(headerProtocolVersion);
+        }
 
-        Object body = message.getBody();
+        final String headerMethod = message.getHeader(Exchange.HTTP_METHOD, 
String.class);
+
+        final HttpMethod httpMethod;
+        if (headerMethod == null) {
+            httpMethod = HttpMethod.GET;
+        } else {
+            httpMethod = HttpMethod.valueOf(headerMethod);
+        }
+
+        FullHttpRequest request = new DefaultFullHttpRequest(protocol, 
httpMethod, uriForRequest);
         if (body != null) {
             // support bodies as native Netty
             ByteBuf buffer;
@@ -492,18 +521,19 @@ public class DefaultNettyHttpBinding implements 
NettyHttpBinding, Cloneable {
                 if (buffer == null) {
                     // fallback to byte array as last resort
                     byte[] data = message.getMandatoryBody(byte[].class);
-                    buffer = NettyConverter.toByteBuffer(data);
+
+                    if (data.length > 0) {
+                        buffer = NettyConverter.toByteBuffer(data);
+                    }
                 }
             }
-            if (buffer != null) {
-                request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, 
HttpMethod.POST, uriForRequest, buffer);
+
+            if (buffer != null && buffer.readableBytes() > 0) {
+                request = request.replace(buffer);
                 int len = buffer.readableBytes();
                 // set content-length
                 
request.headers().set(HttpHeaderNames.CONTENT_LENGTH.toString(), len);
                 LOG.trace("Content-Length: {}", len);
-            } else {
-                // we do not support this kind of body
-                throw new NoTypeConversionAvailableException(body, 
ByteBuf.class);
             }
         }
 
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java
index 8c9d023..4063478 100644
--- 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java
@@ -77,7 +77,7 @@ public class NettyHttpComponent extends NettyComponent 
implements HeaderFilterSt
 
     @Override
     protected Endpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters) throws Exception {
-        NettyConfiguration config;
+        NettyHttpConfiguration config;
         if (getConfiguration() != null) {
             config = getConfiguration().copy();
         } else {
@@ -111,13 +111,14 @@ public class NettyHttpComponent extends NettyComponent 
implements HeaderFilterSt
         }
 
         // we must include the protocol in the remaining
-        boolean hasProtocol = remaining.startsWith("http://";) || 
remaining.startsWith("http:")
-                || remaining.startsWith("https://";) || 
remaining.startsWith("https:");
+        boolean hasProtocol = remaining != null && 
(remaining.startsWith("http://";) || remaining.startsWith("http:")
+                || remaining.startsWith("https://";) || 
remaining.startsWith("https:")
+                || remaining.startsWith("proxy://") || 
remaining.startsWith("proxy:"));
         if (!hasProtocol) {
             // http is the default protocol
             remaining = "http://"; + remaining;
         }
-        boolean hasSlash = remaining.startsWith("http://";) || 
remaining.startsWith("https://";);
+        boolean hasSlash = remaining.startsWith("http://";) || 
remaining.startsWith("https://";) || remaining.startsWith("proxy://");
         if (!hasSlash) {
             // must have double slash after protocol
             if (remaining.startsWith("http:")) {
@@ -136,6 +137,8 @@ public class NettyHttpComponent extends NettyComponent 
implements HeaderFilterSt
                 config.setPort(80);
             } else if (remaining.startsWith("https:")) {
                 config.setPort(443);
+            } else if (remaining.startsWith("proxy:")) {
+                config.setPort(3128); // homage to Squid proxy
             }
         }
         if (config.getPort() == -1) {
@@ -207,20 +210,25 @@ public class NettyHttpComponent extends NettyComponent 
implements HeaderFilterSt
     }
 
     @Override
-    protected NettyConfiguration parseConfiguration(NettyConfiguration 
configuration, String remaining, Map<String, Object> parameters) throws 
Exception {
+    protected NettyHttpConfiguration parseConfiguration(NettyConfiguration 
configuration, String remaining, Map<String, Object> parameters) throws 
Exception {
         // ensure uri is encoded to be valid
         String safe = UnsafeUriCharactersEncoder.encodeHttpURI(remaining);
         URI uri = new URI(safe);
-        configuration.parseURI(uri, parameters, this, "http", "https");
+        configuration.parseURI(uri, parameters, this, "http", "https", 
"proxy");
 
         // force using tcp as the underlying transport
         configuration.setProtocol("tcp");
         configuration.setTextline(false);
 
         if (configuration instanceof NettyHttpConfiguration) {
-            ((NettyHttpConfiguration) configuration).setPath(uri.getPath());
+            final NettyHttpConfiguration httpConfiguration = 
(NettyHttpConfiguration) configuration;
+
+            httpConfiguration.setPath(uri.getPath());
+
+            return httpConfiguration;
         }
-        return configuration;
+
+        throw new IllegalStateException("Received NettyConfiguration instead 
of expected NettyHttpConfiguration, this is not supported.");
     }
 
     public NettyHttpBinding getNettyHttpBinding() {
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpConfiguration.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpConfiguration.java
index 11ec3f4..77be730 100644
--- 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpConfiguration.java
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpConfiguration.java
@@ -97,7 +97,7 @@ public class NettyHttpConfiguration extends 
NettyConfiguration {
     }
 
     /**
-     * The protocol to use which is either http or https
+     * The protocol to use which is either http, https or proxy - a consumer 
only option.
      */
     public void setProtocol(String protocol) {
         this.protocol = protocol;
@@ -318,4 +318,8 @@ public class NettyHttpConfiguration extends 
NettyConfiguration {
     public boolean isUseRelativePath() {
         return this.useRelativePath;
     }
+
+    public boolean isHttpProxy() {
+        return "proxy".equals(super.protocol);
+    }
 }
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerChannelHandler.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerChannelHandler.java
index b852322..211d0c2 100644
--- 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerChannelHandler.java
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerChannelHandler.java
@@ -35,10 +35,12 @@ import io.netty.handler.codec.http.HttpResponse;
 import io.netty.handler.codec.http.HttpUtil;
 import org.apache.camel.Exchange;
 import org.apache.camel.LoggingLevel;
+import org.apache.camel.Message;
 import org.apache.camel.component.netty4.NettyConverter;
 import org.apache.camel.component.netty4.NettyHelper;
 import org.apache.camel.component.netty4.handlers.ServerChannelHandler;
 import org.apache.camel.component.netty4.http.HttpPrincipal;
+import org.apache.camel.component.netty4.http.NettyHttpConfiguration;
 import org.apache.camel.component.netty4.http.NettyHttpConsumer;
 import org.apache.camel.component.netty4.http.NettyHttpSecurityConfiguration;
 import org.apache.camel.component.netty4.http.SecurityAuthenticator;
@@ -264,7 +266,9 @@ public class HttpServerChannelHandler extends 
ServerChannelHandler {
 
     @Override
     protected void beforeProcess(Exchange exchange, final 
ChannelHandlerContext ctx, final Object message) {
-        if (consumer.getConfiguration().isBridgeEndpoint()) {
+        final NettyHttpConfiguration configuration = 
consumer.getConfiguration();
+
+        if (configuration.isBridgeEndpoint()) {
             exchange.setProperty(Exchange.SKIP_GZIP_ENCODING, Boolean.TRUE);
             exchange.setProperty(Exchange.SKIP_WWW_FORM_URLENCODED, 
Boolean.TRUE);
         }
@@ -275,6 +279,11 @@ public class HttpServerChannelHandler extends 
ServerChannelHandler {
             // Just make sure we close the connection this time.
             exchange.setProperty(HttpHeaderNames.CONNECTION.toString(), 
HttpHeaderValues.CLOSE.toString());
         }
+
+        final Message in = exchange.getIn();
+        if (configuration.isHttpProxy()) {
+            in.removeHeader("Proxy-Connection");
+        }
     }
 
     @Override
diff --git 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
index 0d48fee..0722fa8 100644
--- 
a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
+++ 
b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/handlers/HttpServerMultiplexChannelHandler.java
@@ -36,6 +36,7 @@ import io.netty.util.Attribute;
 import io.netty.util.AttributeKey;
 import org.apache.camel.Exchange;
 import org.apache.camel.component.netty4.http.HttpServerConsumerChannelFactory;
+import org.apache.camel.component.netty4.http.NettyHttpConfiguration;
 import org.apache.camel.component.netty4.http.NettyHttpConsumer;
 import org.apache.camel.http.common.CamelServlet;
 import org.apache.camel.support.RestConsumerContextPathMatcher;
@@ -193,6 +194,16 @@ public class HttpServerMultiplexChannelHandler extends 
SimpleChannelInboundHandl
     private HttpServerChannelHandler getHandler(HttpRequest request, String 
method) {
         HttpServerChannelHandler answer = null;
 
+        // quick path to find if there are handlers with HTTP proxy consumers
+        for (final HttpServerChannelHandler handler : consumers) {
+            NettyHttpConsumer consumer = handler.getConsumer();
+
+            final NettyHttpConfiguration configuration = 
consumer.getConfiguration();
+            if (configuration.isHttpProxy()) {
+                return handler;
+            }
+        }
+
         // need to strip out host and port etc, as we only need the 
context-path for matching
         if (method == null) {
             return null;
@@ -222,6 +233,7 @@ public class HttpServerMultiplexChannelHandler extends 
SimpleChannelInboundHandl
         if (answer == null) {
             for (final HttpServerChannelHandler handler : consumers) {
                 NettyHttpConsumer consumer = handler.getConsumer();
+
                 String consumerPath = consumer.getConfiguration().getPath();
                 boolean matchOnUriPrefix = 
consumer.getEndpoint().getConfiguration().isMatchOnUriPrefix();
                 // Just make sure the we get the right consumer path first
diff --git 
a/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/ProxyProtocolTest.java
 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/ProxyProtocolTest.java
new file mode 100644
index 0000000..a4caf17
--- /dev/null
+++ 
b/components/camel-netty4-http/src/test/java/org/apache/camel/component/netty4/http/ProxyProtocolTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * Licensed 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.netty4.http;
+
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.test.AvailablePortFinder;
+import org.apache.commons.io.IOUtils;
+import org.junit.After;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ProxyProtocolTest {
+
+    private final DefaultCamelContext context = new DefaultCamelContext();
+
+    private final int port = AvailablePortFinder.getNextAvailable();
+
+    public ProxyProtocolTest() throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                final int originPort = AvailablePortFinder.getNextAvailable();
+
+                // proxy from http://localhost:port to
+                // http://localhost:originPort/path
+                from("netty-http:proxy://localhost:" + port)
+                    .to("netty-http:http://localhost:"; + originPort);
+
+                // origin service that serves `"origin server"` on
+                // http://localhost:originPort/path
+                from("netty-http:http://localhost:"; + originPort + 
"/path").setBody()
+                    .constant("origin server");
+            }
+        });
+        context.start();
+    }
+
+    @Test
+    public void shouldProvideProxyProtocolSupport() {
+        final NettyHttpEndpoint endpoint = 
context.getEndpoint("netty-http:proxy://localhost", NettyHttpEndpoint.class);
+
+        assertThat(endpoint.getConfiguration().isHttpProxy()).isTrue();
+    }
+
+    @Test
+    public void shouldServeAsHttpProxy() throws Exception {
+        final Proxy proxy = new Proxy(Proxy.Type.HTTP, new 
InetSocketAddress("localhost", port));
+
+        // request for http://test/path will be proxied by 
http://localhost:port
+        // and diverted to http://localhost:originPort/path
+        final HttpURLConnection connection = (HttpURLConnection) new 
URL("http://test/path";).openConnection(proxy);
+
+        try (InputStream stream = connection.getInputStream()) {
+            assertThat(IOUtils.readLines(stream, 
StandardCharsets.UTF_8)).containsOnly("origin server");
+        }
+    }
+
+    @After
+    public void shutdownCamel() throws Exception {
+        context.stop();
+    }
+}
diff --git a/core/camel-api/src/main/java/org/apache/camel/Exchange.java 
b/core/camel-api/src/main/java/org/apache/camel/Exchange.java
index 0606959..ad38c87 100644
--- a/core/camel-api/src/main/java/org/apache/camel/Exchange.java
+++ b/core/camel-api/src/main/java/org/apache/camel/Exchange.java
@@ -141,7 +141,10 @@ public interface Exchange {
     String FILTER_NON_XML_CHARS = "CamelFilterNonXmlChars";
 
     String GROUPED_EXCHANGE = "CamelGroupedExchange";
-    
+
+    String HTTP_SCHEME             = "CamelHttpScheme";
+    String HTTP_HOST               = "CamelHttpHost";
+    String HTTP_PORT               = "CamelHttpPort";
     String HTTP_BASE_URI           = "CamelHttpBaseUri";
     String HTTP_CHARACTER_ENCODING = "CamelHttpCharacterEncoding";
     String HTTP_METHOD             = "CamelHttpMethod";
diff --git 
a/platforms/spring-boot/components-starter/camel-netty4-http-starter/src/main/java/org/apache/camel/component/netty4/http/springboot/NettyHttpComponentConfiguration.java
 
b/platforms/spring-boot/components-starter/camel-netty4-http-starter/src/main/java/org/apache/camel/component/netty4/http/springboot/NettyHttpComponentConfiguration.java
index 0848e9f..d8e7fcd 100644
--- 
a/platforms/spring-boot/components-starter/camel-netty4-http-starter/src/main/java/org/apache/camel/component/netty4/http/springboot/NettyHttpComponentConfiguration.java
+++ 
b/platforms/spring-boot/components-starter/camel-netty4-http-starter/src/main/java/org/apache/camel/component/netty4/http/springboot/NettyHttpComponentConfiguration.java
@@ -165,7 +165,8 @@ public class NettyHttpComponentConfiguration
     public static class NettyHttpConfigurationNestedConfiguration {
         public static final Class CAMEL_NESTED_CLASS = 
org.apache.camel.component.netty4.http.NettyHttpConfiguration.class;
         /**
-         * The protocol to use which is either http or https
+         * The protocol to use which is either http, https or proxy - a 
consumer
+         * only option.
          */
         private String protocol;
         /**

Reply via email to