You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2020/10/23 07:14:34 UTC

[camel] branch master updated: CAMEL-15716: Add WebSocket client support for subprotocols to camel-vertx-websocket (#4498)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 77f7ea5  CAMEL-15716: Add WebSocket client support for subprotocols to camel-vertx-websocket (#4498)
77f7ea5 is described below

commit 77f7ea5305ce85e1bd9ef6e38f97a47ac2587b30
Author: James Netherton <ja...@users.noreply.github.com>
AuthorDate: Fri Oct 23 08:14:19 2020 +0100

    CAMEL-15716: Add WebSocket client support for subprotocols to camel-vertx-websocket (#4498)
---
 .../camel/catalog/docs/vertx-websocket-component.adoc    |  3 ++-
 .../websocket/VertxWebsocketEndpointConfigurer.java      |  5 +++++
 .../websocket/VertxWebsocketEndpointUriFactory.java      |  3 ++-
 .../camel/component/vertx/websocket/vertx-websocket.json |  1 +
 .../src/main/docs/vertx-websocket-component.adoc         |  3 ++-
 .../vertx/websocket/VertxWebsocketConfiguration.java     | 13 +++++++++++++
 .../vertx/websocket/VertxWebsocketEndpoint.java          | 16 +++++++++++++++-
 .../websocket/VertxWebsocketExternalServerTest.java      | 15 ++++++++++++---
 .../dsl/VertxWebsocketEndpointBuilderFactory.java        | 13 +++++++++++++
 .../modules/ROOT/pages/vertx-websocket-component.adoc    |  3 ++-
 10 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/vertx-websocket-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/vertx-websocket-component.adoc
index 48306d1..bbba090 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/vertx-websocket-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/vertx-websocket-component.adoc
@@ -80,7 +80,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (12 parameters):
+=== Query Parameters (13 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -93,6 +93,7 @@ with the following path and query parameters:
 | *exceptionHandler* (consumer) | To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored. |  | ExceptionHandler
 | *exchangePattern* (consumer) | Sets the exchange pattern when the consumer creates an exchange. There are 3 enums and the value can be one of: InOnly, InOut, InOptionalOut |  | ExchangePattern
 | *clientOptions* (producer) | Sets customized options for configuring the WebSocket client used in the producer |  | HttpClientOptions
+| *clientSubProtocols* (producer) | Comma separated list of WebSocket subprotocols that the client should use for the Sec-WebSocket-Protocol header |  | String
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 | *sendToAll* (producer) | To send to all websocket subscribers. Can be used to configure on endpoint level, instead of having to use the VertxWebsocketConstants.SEND_TO_ALL header on the message. | false | boolean
 | *basicPropertyBinding* (advanced) | Whether the endpoint should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities | false | boolean
diff --git a/components/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointConfigurer.java b/components/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointConfigurer.java
index 5e5ffa0..e8060ce 100644
--- a/components/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointConfigurer.java
+++ b/components/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointConfigurer.java
@@ -28,6 +28,7 @@ public class VertxWebsocketEndpointConfigurer extends PropertyConfigurerSupport
         map.put("exceptionHandler", org.apache.camel.spi.ExceptionHandler.class);
         map.put("exchangePattern", org.apache.camel.ExchangePattern.class);
         map.put("clientOptions", io.vertx.core.http.HttpClientOptions.class);
+        map.put("clientSubProtocols", java.lang.String.class);
         map.put("lazyStartProducer", boolean.class);
         map.put("sendToAll", boolean.class);
         map.put("basicPropertyBinding", boolean.class);
@@ -48,6 +49,8 @@ public class VertxWebsocketEndpointConfigurer extends PropertyConfigurerSupport
         case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true;
         case "clientoptions":
         case "clientOptions": target.getConfiguration().setClientOptions(property(camelContext, io.vertx.core.http.HttpClientOptions.class, value)); return true;
+        case "clientsubprotocols":
+        case "clientSubProtocols": target.getConfiguration().setClientSubProtocols(property(camelContext, java.lang.String.class, value)); return true;
         case "exceptionhandler":
         case "exceptionHandler": target.setExceptionHandler(property(camelContext, org.apache.camel.spi.ExceptionHandler.class, value)); return true;
         case "exchangepattern":
@@ -83,6 +86,8 @@ public class VertxWebsocketEndpointConfigurer extends PropertyConfigurerSupport
         case "bridgeErrorHandler": return target.isBridgeErrorHandler();
         case "clientoptions":
         case "clientOptions": return target.getConfiguration().getClientOptions();
+        case "clientsubprotocols":
+        case "clientSubProtocols": return target.getConfiguration().getClientSubProtocols();
         case "exceptionhandler":
         case "exceptionHandler": return target.getExceptionHandler();
         case "exchangepattern":
diff --git a/components/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointUriFactory.java b/components/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointUriFactory.java
index 283ef83..7127166 100644
--- a/components/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointUriFactory.java
+++ b/components/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointUriFactory.java
@@ -20,7 +20,7 @@ public class VertxWebsocketEndpointUriFactory extends org.apache.camel.support.c
     private static final Set<String> PROPERTY_NAMES;
     private static final Set<String> SECRET_PROPERTY_NAMES;
     static {
-        Set<String> props = new HashSet<>(15);
+        Set<String> props = new HashSet<>(16);
         props.add("clientOptions");
         props.add("basicPropertyBinding");
         props.add("synchronous");
@@ -36,6 +36,7 @@ public class VertxWebsocketEndpointUriFactory extends org.apache.camel.support.c
         props.add("port");
         props.add("host");
         props.add("exceptionHandler");
+        props.add("clientSubProtocols");
         PROPERTY_NAMES = Collections.unmodifiableSet(props);
         SECRET_PROPERTY_NAMES = Collections.emptySet();
     }
diff --git a/components/camel-vertx-websocket/src/generated/resources/org/apache/camel/component/vertx/websocket/vertx-websocket.json b/components/camel-vertx-websocket/src/generated/resources/org/apache/camel/component/vertx/websocket/vertx-websocket.json
index ea1c2bd..3d408be 100644
--- a/components/camel-vertx-websocket/src/generated/resources/org/apache/camel/component/vertx/websocket/vertx-websocket.json
+++ b/components/camel-vertx-websocket/src/generated/resources/org/apache/camel/component/vertx/websocket/vertx-websocket.json
@@ -41,6 +41,7 @@
     "exceptionHandler": { "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with [...]
     "exchangePattern": { "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut", "InOptionalOut" ], "deprecated": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
     "clientOptions": { "kind": "parameter", "displayName": "Client Options", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "io.vertx.core.http.HttpClientOptions", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration", "configurationField": "configuration", "description": "Sets customized options for configuring the WebSocket client used in the producer" },
+    "clientSubProtocols": { "kind": "parameter", "displayName": "Client Sub Protocols", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration", "configurationField": "configuration", "description": "Comma separated list of WebSocket subprotocols that the client should use for the Sec-WebSocket-Protocol [...]
     "lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the  [...]
     "sendToAll": { "kind": "parameter", "displayName": "Send To All", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration", "configurationField": "configuration", "description": "To send to all websocket subscribers. Can be used to configure on endpoint level, instead of having to use  [...]
     "basicPropertyBinding": { "kind": "parameter", "displayName": "Basic Property Binding", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "Whether the endpoint should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities" },
diff --git a/components/camel-vertx-websocket/src/main/docs/vertx-websocket-component.adoc b/components/camel-vertx-websocket/src/main/docs/vertx-websocket-component.adoc
index 48306d1..bbba090 100644
--- a/components/camel-vertx-websocket/src/main/docs/vertx-websocket-component.adoc
+++ b/components/camel-vertx-websocket/src/main/docs/vertx-websocket-component.adoc
@@ -80,7 +80,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (12 parameters):
+=== Query Parameters (13 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -93,6 +93,7 @@ with the following path and query parameters:
 | *exceptionHandler* (consumer) | To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored. |  | ExceptionHandler
 | *exchangePattern* (consumer) | Sets the exchange pattern when the consumer creates an exchange. There are 3 enums and the value can be one of: InOnly, InOut, InOptionalOut |  | ExchangePattern
 | *clientOptions* (producer) | Sets customized options for configuring the WebSocket client used in the producer |  | HttpClientOptions
+| *clientSubProtocols* (producer) | Comma separated list of WebSocket subprotocols that the client should use for the Sec-WebSocket-Protocol header |  | String
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 | *sendToAll* (producer) | To send to all websocket subscribers. Can be used to configure on endpoint level, instead of having to use the VertxWebsocketConstants.SEND_TO_ALL header on the message. | false | boolean
 | *basicPropertyBinding* (advanced) | Whether the endpoint should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities | false | boolean
diff --git a/components/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConfiguration.java b/components/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConfiguration.java
index 65fcc50..c77981a 100644
--- a/components/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConfiguration.java
+++ b/components/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConfiguration.java
@@ -45,6 +45,8 @@ public class VertxWebsocketConfiguration {
     private HttpClientOptions clientOptions;
     @UriParam(label = "producer")
     private boolean sendToAll;
+    @UriParam(label = "producer")
+    private String clientSubProtocols;
     @UriParam(label = "security")
     private SSLContextParameters sslContextParameters;
 
@@ -150,4 +152,15 @@ public class VertxWebsocketConfiguration {
     public void setRouter(Router router) {
         this.router = router;
     }
+
+    /**
+     * Comma separated list of WebSocket subprotocols that the client should use for the Sec-WebSocket-Protocol header
+     */
+    public void setClientSubProtocols(String clientSubProtocols) {
+        this.clientSubProtocols = clientSubProtocols;
+    }
+
+    public String getClientSubProtocols() {
+        return clientSubProtocols;
+    }
 }
diff --git a/components/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpoint.java b/components/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpoint.java
index d222bc2..2f2d932 100644
--- a/components/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpoint.java
+++ b/components/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpoint.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.component.vertx.websocket;
 
+import java.util.Arrays;
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
@@ -27,6 +28,7 @@ import io.vertx.core.http.HttpClient;
 import io.vertx.core.http.HttpClientOptions;
 import io.vertx.core.http.ServerWebSocket;
 import io.vertx.core.http.WebSocket;
+import io.vertx.core.http.WebSocketConnectOptions;
 import org.apache.camel.Category;
 import org.apache.camel.Consumer;
 import org.apache.camel.Exchange;
@@ -36,6 +38,7 @@ import org.apache.camel.spi.UriEndpoint;
 import org.apache.camel.spi.UriParam;
 import org.apache.camel.support.DefaultEndpoint;
 import org.apache.camel.support.jsse.SSLContextParameters;
+import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -105,8 +108,19 @@ public class VertxWebsocketEndpoint extends DefaultEndpoint {
 
             client = getVertx().createHttpClient(options);
 
+            WebSocketConnectOptions connectOptions = new WebSocketConnectOptions();
+            connectOptions.setHost(configuration.getHost());
+            connectOptions.setPort(configuration.getPort());
+            connectOptions.setURI(configuration.getPath());
+            connectOptions.setSsl(options.isSsl());
+
+            String subProtocols = configuration.getClientSubProtocols();
+            if (ObjectHelper.isNotEmpty(subProtocols)) {
+                connectOptions.setSubProtocols(Arrays.asList(subProtocols.split(",")));
+            }
+
             CompletableFuture<WebSocket> future = new CompletableFuture<>();
-            client.webSocket(configuration.getPort(), configuration.getHost(), configuration.getPath(), result -> {
+            client.webSocket(connectOptions, result -> {
                 if (!result.failed()) {
                     LOG.info("Connected to WebSocket on {}:{}", configuration.getHost(), configuration.getPort());
                     future.complete(result.result());
diff --git a/components/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketExternalServerTest.java b/components/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketExternalServerTest.java
index 0b09f06..8214f06 100644
--- a/components/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketExternalServerTest.java
+++ b/components/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketExternalServerTest.java
@@ -16,11 +16,13 @@
  */
 package org.apache.camel.component.vertx.websocket;
 
+import java.util.Arrays;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 import io.vertx.core.Handler;
 import io.vertx.core.Vertx;
+import io.vertx.core.http.HttpServerOptions;
 import io.vertx.core.http.HttpServerRequest;
 import io.vertx.core.http.ServerWebSocket;
 import io.vertx.ext.web.Route;
@@ -34,6 +36,7 @@ import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 public class VertxWebsocketExternalServerTest extends VertxWebSocketTestSupport {
@@ -50,6 +53,9 @@ public class VertxWebsocketExternalServerTest extends VertxWebSocketTestSupport
             @Override
             public void handle(RoutingContext context) {
                 HttpServerRequest request = context.request();
+                String subProtocols = request.getHeader("Sec-WebSocket-Protocol");
+                assertEquals("foo,bar,cheese", subProtocols);
+
                 ServerWebSocket webSocket = request.upgrade();
                 webSocket.textMessageHandler(new Handler<String>() {
                     @Override
@@ -60,7 +66,10 @@ public class VertxWebsocketExternalServerTest extends VertxWebSocketTestSupport
             }
         });
 
-        VertxWebsocketHostConfiguration configuration = new VertxWebsocketHostConfiguration(vertx, router, null, null);
+        HttpServerOptions options = new HttpServerOptions();
+        options.setWebSocketSubProtocols(Arrays.asList("foo", "bar", "cheese"));
+
+        VertxWebsocketHostConfiguration configuration = new VertxWebsocketHostConfiguration(vertx, router, options, null);
         VertxWebsocketHostKey key = new VertxWebsocketHostKey("localhost", 0);
         VertxWebsocketHost host = new VertxWebsocketHost(configuration, key);
         host.start();
@@ -70,10 +79,10 @@ public class VertxWebsocketExternalServerTest extends VertxWebSocketTestSupport
             @Override
             public void configure() throws Exception {
                 from("direct:start")
-                        .toD("vertx-websocket:localhost:${header.port}/ws");
+                        .toD("vertx-websocket:localhost:${header.port}/ws?clientSubProtocols=foo,bar,cheese");
 
                 from("vertx-websocket:localhost:" + port + "/test")
-                        .toF("vertx-websocket:localhost:%d/ws", host.getPort());
+                        .toF("vertx-websocket:localhost:%d/ws?clientSubProtocols=foo,bar,cheese", host.getPort());
             }
         });
 
diff --git a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/VertxWebsocketEndpointBuilderFactory.java b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/VertxWebsocketEndpointBuilderFactory.java
index 1b785a1..6d7d51d 100644
--- a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/VertxWebsocketEndpointBuilderFactory.java
+++ b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/VertxWebsocketEndpointBuilderFactory.java
@@ -334,6 +334,19 @@ public interface VertxWebsocketEndpointBuilderFactory {
             return this;
         }
         /**
+         * Comma separated list of WebSocket subprotocols that the client should
+         * use for the Sec-WebSocket-Protocol header.
+         * 
+         * The option is a: <code>java.lang.String</code> type.
+         * 
+         * Group: producer
+         */
+        default VertxWebsocketEndpointProducerBuilder clientSubProtocols(
+                String clientSubProtocols) {
+            doSetProperty("clientSubProtocols", clientSubProtocols);
+            return this;
+        }
+        /**
          * Whether the producer should be started lazy (on the first message).
          * By starting lazy you can use this to allow CamelContext and routes to
          * startup in situations where a producer may otherwise fail during
diff --git a/docs/components/modules/ROOT/pages/vertx-websocket-component.adoc b/docs/components/modules/ROOT/pages/vertx-websocket-component.adoc
index 4930590..41c3aac 100644
--- a/docs/components/modules/ROOT/pages/vertx-websocket-component.adoc
+++ b/docs/components/modules/ROOT/pages/vertx-websocket-component.adoc
@@ -82,7 +82,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (12 parameters):
+=== Query Parameters (13 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -95,6 +95,7 @@ with the following path and query parameters:
 | *exceptionHandler* (consumer) | To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored. |  | ExceptionHandler
 | *exchangePattern* (consumer) | Sets the exchange pattern when the consumer creates an exchange. There are 3 enums and the value can be one of: InOnly, InOut, InOptionalOut |  | ExchangePattern
 | *clientOptions* (producer) | Sets customized options for configuring the WebSocket client used in the producer |  | HttpClientOptions
+| *clientSubProtocols* (producer) | Comma separated list of WebSocket subprotocols that the client should use for the Sec-WebSocket-Protocol header |  | String
 | *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
 | *sendToAll* (producer) | To send to all websocket subscribers. Can be used to configure on endpoint level, instead of having to use the VertxWebsocketConstants.SEND_TO_ALL header on the message. | false | boolean
 | *basicPropertyBinding* (advanced) | Whether the endpoint should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities | false | boolean