This is an automated email from the ASF dual-hosted git repository.
oscerd pushed a commit to branch camel-4.14.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.14.x by this push:
new 508fc15deca9 CAMEL-23532: camel-vertx-websocket /
camel-atmosphere-websocket / camel-iggy - use dedicated HeaderFilterStrategy
aligned with sibling components (#23352)
508fc15deca9 is described below
commit 508fc15deca97ba373eb3881a00e220eab9ec428
Author: Andrea Cosentino <[email protected]>
AuthorDate: Wed May 20 10:27:13 2026 +0200
CAMEL-23532: camel-vertx-websocket / camel-atmosphere-websocket /
camel-iggy - use dedicated HeaderFilterStrategy aligned with sibling components
(#23352)
Apply a HeaderFilterStrategy on the inbound header mapping of the
vertx-websocket, atmosphere-websocket and iggy consumers, aligning them
with the pattern already used by camel-coap (CAMEL-23222), camel-cometd
(CAMEL-23507) and camel-nats (CAMEL-23515). vertx-websocket and iggy gain
a new VertxWebsocketHeaderFilterStrategy / IggyHeaderFilterStrategy plus a
headerFilterStrategy endpoint option; atmosphere-websocket reuses the
HeaderFilterStrategy it already inherits from the HTTP/servlet stack.
Includes unit tests and an upgrade-guide note.
Closes #23285
(cherry picked from commit 1e776238202edb9d98972cff558e12b53e499647)
Signed-off-by: Andrea Cosentino <[email protected]>
Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
---
.../camel/catalog/components/vertx-websocket.json | 9 +-
.../atmosphere/websocket/WebsocketConsumer.java | 7 +-
.../VertxWebsocketEndpointConfigurer.java | 6 ++
.../VertxWebsocketEndpointUriFactory.java | 3 +-
.../component/vertx/websocket/vertx-websocket.json | 9 +-
.../vertx/websocket/VertxWebsocketConsumer.java | 16 +++-
.../vertx/websocket/VertxWebsocketEndpoint.java | 23 +++++-
.../VertxWebsocketHeaderFilterStrategy.java | 34 ++++++++
.../VertxWebsocketHeaderFilterStrategyTest.java | 53 ++++++++++++
.../ROOT/pages/camel-4x-upgrade-guide-4_14.adoc | 19 +++++
.../dsl/VertxWebsocketEndpointBuilderFactory.java | 96 ++++++++++++++++++++++
11 files changed, 262 insertions(+), 13 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/vertx-websocket.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/vertx-websocket.json
index 158a18f9049e..028135760fd5 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/vertx-websocket.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/vertx-websocket.json
@@ -61,9 +61,10 @@
"sendToAll": { "index": 15, "kind": "parameter", "displayName": "Send To
All", "group": "producer", "label": "producer", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": 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 at the endp [...]
"clientOptions": { "index": 16, "kind": "parameter", "displayName":
"Client Options", "group": "producer (advanced)", "label": "producer,advanced",
"required": false, "type": "object", "javaType":
"io.vertx.core.http.HttpClientOptions", "deprecated": false, "autowired":
false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "Sets customized options
for configuring th [...]
"lazyStartProducer": { "index": 17, "kind": "parameter", "displayName":
"Lazy Start Producer", "group": "producer (advanced)", "label":
"producer,advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": 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 produ [...]
- "allowOriginHeader": { "index": 18, "kind": "parameter", "displayName":
"Allow Origin Header", "group": "security", "label": "security", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true,
"configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "Whether the WebSocket
client should add the Origin header t [...]
- "handshakeHeaders": { "index": 19, "kind": "parameter", "displayName":
"Handshake Headers", "group": "security", "label": "security", "required":
false, "type": "object", "javaType": "java.util.Map<java.lang.String,
java.lang.Object>", "prefix": "handshake.", "multiValue": true, "deprecated":
false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": [...]
- "originHeaderUrl": { "index": 20, "kind": "parameter", "displayName":
"Origin Header Url", "group": "security", "label": "security", "required":
false, "type": "string", "javaType": "java.lang.String", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "The value of the Origin
header that the WebSocket client should use on the We [...]
- "sslContextParameters": { "index": 21, "kind": "parameter", "displayName":
"Ssl Context Parameters", "group": "security", "label": "security", "required":
false, "type": "object", "javaType":
"org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "To configure security
using SSLCo [...]
+ "headerFilterStrategy": { "index": 18, "kind": "parameter", "displayName":
"Header Filter Strategy", "group": "advanced", "label": "advanced", "required":
false, "type": "object", "javaType":
"org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired":
false, "secret": false, "description": "To use a custom HeaderFilterStrategy to
filter header to and from Camel message." },
+ "allowOriginHeader": { "index": 19, "kind": "parameter", "displayName":
"Allow Origin Header", "group": "security", "label": "security", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true,
"configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "Whether the WebSocket
client should add the Origin header t [...]
+ "handshakeHeaders": { "index": 20, "kind": "parameter", "displayName":
"Handshake Headers", "group": "security", "label": "security", "required":
false, "type": "object", "javaType": "java.util.Map<java.lang.String,
java.lang.Object>", "prefix": "handshake.", "multiValue": true, "deprecated":
false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": [...]
+ "originHeaderUrl": { "index": 21, "kind": "parameter", "displayName":
"Origin Header Url", "group": "security", "label": "security", "required":
false, "type": "string", "javaType": "java.lang.String", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "The value of the Origin
header that the WebSocket client should use on the We [...]
+ "sslContextParameters": { "index": 22, "kind": "parameter", "displayName":
"Ssl Context Parameters", "group": "security", "label": "security", "required":
false, "type": "object", "javaType":
"org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "To configure security
using SSLCo [...]
}
}
diff --git
a/components/camel-atmosphere-websocket/src/main/java/org/apache/camel/component/atmosphere/websocket/WebsocketConsumer.java
b/components/camel-atmosphere-websocket/src/main/java/org/apache/camel/component/atmosphere/websocket/WebsocketConsumer.java
index 5fbfb09a5510..628c46c4f450 100644
---
a/components/camel-atmosphere-websocket/src/main/java/org/apache/camel/component/atmosphere/websocket/WebsocketConsumer.java
+++
b/components/camel-atmosphere-websocket/src/main/java/org/apache/camel/component/atmosphere/websocket/WebsocketConsumer.java
@@ -30,6 +30,7 @@ import org.apache.camel.AsyncCallback;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.component.servlet.ServletConsumer;
+import org.apache.camel.spi.HeaderFilterStrategy;
import org.atmosphere.cpr.ApplicationConfig;
import org.atmosphere.cpr.AtmosphereFramework;
import org.atmosphere.cpr.AtmosphereFrameworkInitializer;
@@ -103,8 +104,12 @@ public class WebsocketConsumer extends ServletConsumer {
exchange.getIn().setHeader(WebsocketConstants.CONNECTION_KEY,
connectionKey);
exchange.getIn().setHeader(WebsocketConstants.EVENT_TYPE, eventType);
+ HeaderFilterStrategy headerFilterStrategy =
getEndpoint().getHeaderFilterStrategy();
for (Map.Entry<String, String> param : queryMap.entrySet()) {
- exchange.getIn().setHeader(param.getKey(), param.getValue());
+ if (headerFilterStrategy == null
+ ||
!headerFilterStrategy.applyFilterToExternalHeaders(param.getKey(),
param.getValue(), exchange)) {
+ exchange.getIn().setHeader(param.getKey(), param.getValue());
+ }
}
// use default consumer callback
diff --git
a/components/camel-vertx/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointConfigurer.java
b/components/camel-vertx/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointConfigurer.java
index 1fea496c4e88..907f01d0bf1e 100644
---
a/components/camel-vertx/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointConfigurer.java
+++
b/components/camel-vertx/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointConfigurer.java
@@ -43,6 +43,8 @@ public class VertxWebsocketEndpointConfigurer extends
PropertyConfigurerSupport
case "fireWebSocketConnectionEvents":
target.getConfiguration().setFireWebSocketConnectionEvents(property(camelContext,
boolean.class, value)); return true;
case "handshakeheaders":
case "handshakeHeaders":
target.getConfiguration().setHandshakeHeaders(property(camelContext,
java.util.Map.class, value)); return true;
+ case "headerfilterstrategy":
+ case "headerFilterStrategy":
target.setHeaderFilterStrategy(property(camelContext,
org.apache.camel.spi.HeaderFilterStrategy.class, value)); return true;
case "lazystartproducer":
case "lazyStartProducer":
target.setLazyStartProducer(property(camelContext, boolean.class, value));
return true;
case "maxreconnectattempts":
@@ -87,6 +89,8 @@ public class VertxWebsocketEndpointConfigurer extends
PropertyConfigurerSupport
case "fireWebSocketConnectionEvents": return boolean.class;
case "handshakeheaders":
case "handshakeHeaders": return java.util.Map.class;
+ case "headerfilterstrategy":
+ case "headerFilterStrategy": return
org.apache.camel.spi.HeaderFilterStrategy.class;
case "lazystartproducer":
case "lazyStartProducer": return boolean.class;
case "maxreconnectattempts":
@@ -132,6 +136,8 @@ public class VertxWebsocketEndpointConfigurer extends
PropertyConfigurerSupport
case "fireWebSocketConnectionEvents": return
target.getConfiguration().isFireWebSocketConnectionEvents();
case "handshakeheaders":
case "handshakeHeaders": return
target.getConfiguration().getHandshakeHeaders();
+ case "headerfilterstrategy":
+ case "headerFilterStrategy": return target.getHeaderFilterStrategy();
case "lazystartproducer":
case "lazyStartProducer": return target.isLazyStartProducer();
case "maxreconnectattempts":
diff --git
a/components/camel-vertx/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointUriFactory.java
b/components/camel-vertx/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointUriFactory.java
index 47f7fac1be1f..5198b0100a48 100644
---
a/components/camel-vertx/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointUriFactory.java
+++
b/components/camel-vertx/camel-vertx-websocket/src/generated/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpointUriFactory.java
@@ -23,7 +23,7 @@ public class VertxWebsocketEndpointUriFactory extends
org.apache.camel.support.c
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Set<String> MULTI_VALUE_PREFIXES;
static {
- Set<String> props = new HashSet<>(22);
+ Set<String> props = new HashSet<>(23);
props.add("allowOriginHeader");
props.add("allowedOriginPattern");
props.add("bridgeErrorHandler");
@@ -34,6 +34,7 @@ public class VertxWebsocketEndpointUriFactory extends
org.apache.camel.support.c
props.add("exchangePattern");
props.add("fireWebSocketConnectionEvents");
props.add("handshakeHeaders");
+ props.add("headerFilterStrategy");
props.add("host");
props.add("lazyStartProducer");
props.add("maxReconnectAttempts");
diff --git
a/components/camel-vertx/camel-vertx-websocket/src/generated/resources/META-INF/org/apache/camel/component/vertx/websocket/vertx-websocket.json
b/components/camel-vertx/camel-vertx-websocket/src/generated/resources/META-INF/org/apache/camel/component/vertx/websocket/vertx-websocket.json
index 158a18f9049e..028135760fd5 100644
---
a/components/camel-vertx/camel-vertx-websocket/src/generated/resources/META-INF/org/apache/camel/component/vertx/websocket/vertx-websocket.json
+++
b/components/camel-vertx/camel-vertx-websocket/src/generated/resources/META-INF/org/apache/camel/component/vertx/websocket/vertx-websocket.json
@@ -61,9 +61,10 @@
"sendToAll": { "index": 15, "kind": "parameter", "displayName": "Send To
All", "group": "producer", "label": "producer", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": 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 at the endp [...]
"clientOptions": { "index": 16, "kind": "parameter", "displayName":
"Client Options", "group": "producer (advanced)", "label": "producer,advanced",
"required": false, "type": "object", "javaType":
"io.vertx.core.http.HttpClientOptions", "deprecated": false, "autowired":
false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "Sets customized options
for configuring th [...]
"lazyStartProducer": { "index": 17, "kind": "parameter", "displayName":
"Lazy Start Producer", "group": "producer (advanced)", "label":
"producer,advanced", "required": false, "type": "boolean", "javaType":
"boolean", "deprecated": false, "autowired": 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 produ [...]
- "allowOriginHeader": { "index": 18, "kind": "parameter", "displayName":
"Allow Origin Header", "group": "security", "label": "security", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true,
"configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "Whether the WebSocket
client should add the Origin header t [...]
- "handshakeHeaders": { "index": 19, "kind": "parameter", "displayName":
"Handshake Headers", "group": "security", "label": "security", "required":
false, "type": "object", "javaType": "java.util.Map<java.lang.String,
java.lang.Object>", "prefix": "handshake.", "multiValue": true, "deprecated":
false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": [...]
- "originHeaderUrl": { "index": 20, "kind": "parameter", "displayName":
"Origin Header Url", "group": "security", "label": "security", "required":
false, "type": "string", "javaType": "java.lang.String", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "The value of the Origin
header that the WebSocket client should use on the We [...]
- "sslContextParameters": { "index": 21, "kind": "parameter", "displayName":
"Ssl Context Parameters", "group": "security", "label": "security", "required":
false, "type": "object", "javaType":
"org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "To configure security
using SSLCo [...]
+ "headerFilterStrategy": { "index": 18, "kind": "parameter", "displayName":
"Header Filter Strategy", "group": "advanced", "label": "advanced", "required":
false, "type": "object", "javaType":
"org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired":
false, "secret": false, "description": "To use a custom HeaderFilterStrategy to
filter header to and from Camel message." },
+ "allowOriginHeader": { "index": 19, "kind": "parameter", "displayName":
"Allow Origin Header", "group": "security", "label": "security", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true,
"configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "Whether the WebSocket
client should add the Origin header t [...]
+ "handshakeHeaders": { "index": 20, "kind": "parameter", "displayName":
"Handshake Headers", "group": "security", "label": "security", "required":
false, "type": "object", "javaType": "java.util.Map<java.lang.String,
java.lang.Object>", "prefix": "handshake.", "multiValue": true, "deprecated":
false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": [...]
+ "originHeaderUrl": { "index": 21, "kind": "parameter", "displayName":
"Origin Header Url", "group": "security", "label": "security", "required":
false, "type": "string", "javaType": "java.lang.String", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "The value of the Origin
header that the WebSocket client should use on the We [...]
+ "sslContextParameters": { "index": 22, "kind": "parameter", "displayName":
"Ssl Context Parameters", "group": "security", "label": "security", "required":
false, "type": "object", "javaType":
"org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.vertx.websocket.VertxWebsocketConfiguration",
"configurationField": "configuration", "description": "To configure security
using SSLCo [...]
}
}
diff --git
a/components/camel-vertx/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumer.java
b/components/camel-vertx/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumer.java
index 235bbbc4c363..98194669d9a3 100644
---
a/components/camel-vertx/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumer.java
+++
b/components/camel-vertx/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketConsumer.java
@@ -25,6 +25,7 @@ import io.vertx.ext.web.RoutingContext;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.Processor;
+import org.apache.camel.spi.HeaderFilterStrategy;
import org.apache.camel.support.DefaultConsumer;
/**
@@ -106,10 +107,21 @@ public class VertxWebsocketConsumer extends
DefaultConsumer {
message.setHeader(VertxWebsocketConstants.REMOTE_ADDRESS, remote);
message.setHeader(VertxWebsocketConstants.CONNECTION_KEY,
connectionKey);
message.setHeader(VertxWebsocketConstants.EVENT, event);
+ HeaderFilterStrategy headerFilterStrategy =
getEndpoint().getHeaderFilterStrategy();
routingContext.queryParams()
- .forEach((name, value) ->
VertxWebsocketHelper.appendHeader(headers, name, value));
+ .forEach((name, value) -> {
+ if (headerFilterStrategy == null
+ ||
!headerFilterStrategy.applyFilterToExternalHeaders(name, value, exchange)) {
+ VertxWebsocketHelper.appendHeader(headers, name,
value);
+ }
+ });
routingContext.pathParams()
- .forEach((name, value) ->
VertxWebsocketHelper.appendHeader(headers, name, value));
+ .forEach((name, value) -> {
+ if (headerFilterStrategy == null
+ ||
!headerFilterStrategy.applyFilterToExternalHeaders(name, value, exchange)) {
+ VertxWebsocketHelper.appendHeader(headers, name,
value);
+ }
+ });
}
protected void processExchange(Exchange exchange, RoutingContext
routingContext) {
diff --git
a/components/camel-vertx/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpoint.java
b/components/camel-vertx/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpoint.java
index 28c6cadce0c9..46439641d075 100644
---
a/components/camel-vertx/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpoint.java
+++
b/components/camel-vertx/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketEndpoint.java
@@ -36,6 +36,8 @@ import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.component.vertx.common.VertxHelper;
import org.apache.camel.spi.EndpointServiceLocation;
+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.support.DefaultEndpoint;
@@ -52,12 +54,15 @@ import static
org.apache.camel.component.vertx.websocket.VertxWebsocketConstants
@UriEndpoint(firstVersion = "3.5.0", scheme = "vertx-websocket", title =
"Vert.x WebSocket",
syntax = "vertx-websocket:host:port/path", category = {
Category.HTTP, Category.NETWORKING },
headersClass = VertxWebsocketConstants.class, lenientProperties =
true)
-public class VertxWebsocketEndpoint extends DefaultEndpoint implements
EndpointServiceLocation {
+public class VertxWebsocketEndpoint extends DefaultEndpoint implements
EndpointServiceLocation, HeaderFilterStrategyAware {
private static final Logger LOG =
LoggerFactory.getLogger(VertxWebsocketEndpoint.class);
@UriParam
private VertxWebsocketConfiguration configuration;
+ @UriParam(label = "advanced",
+ description = "To use a custom HeaderFilterStrategy to filter
header to and from Camel message.")
+ private HeaderFilterStrategy headerFilterStrategy;
private HttpClient client;
private WebSocket webSocket;
@@ -124,6 +129,22 @@ public class VertxWebsocketEndpoint extends
DefaultEndpoint implements EndpointS
return configuration;
}
+ @Override
+ public HeaderFilterStrategy getHeaderFilterStrategy() {
+ if (headerFilterStrategy == null) {
+ headerFilterStrategy = new VertxWebsocketHeaderFilterStrategy();
+ }
+ return headerFilterStrategy;
+ }
+
+ /**
+ * To use a custom {@link org.apache.camel.spi.HeaderFilterStrategy} to
filter header to and from Camel message.
+ */
+ @Override
+ public void setHeaderFilterStrategy(HeaderFilterStrategy
headerFilterStrategy) {
+ this.headerFilterStrategy = headerFilterStrategy;
+ }
+
protected Vertx getVertx() {
return getComponent().getVertx();
}
diff --git
a/components/camel-vertx/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketHeaderFilterStrategy.java
b/components/camel-vertx/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketHeaderFilterStrategy.java
new file mode 100644
index 000000000000..232de276eb63
--- /dev/null
+++
b/components/camel-vertx/camel-vertx-websocket/src/main/java/org/apache/camel/component/vertx/websocket/VertxWebsocketHeaderFilterStrategy.java
@@ -0,0 +1,34 @@
+/*
+ * 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.vertx.websocket;
+
+import org.apache.camel.support.DefaultHeaderFilterStrategy;
+
+/**
+ * Default header filter strategy for Vert.x WebSocket endpoints.
+ * <p>
+ * Filters out Camel internal headers (starting with "Camel" or "camel") in
both directions to prevent external
+ * WebSocket clients from injecting internal Camel headers via query or path
parameters.
+ */
+public class VertxWebsocketHeaderFilterStrategy extends
DefaultHeaderFilterStrategy {
+
+ public VertxWebsocketHeaderFilterStrategy() {
+ setLowerCase(true);
+ setOutFilterStartsWith(CAMEL_FILTER_STARTS_WITH);
+ setInFilterStartsWith(CAMEL_FILTER_STARTS_WITH);
+ }
+}
diff --git
a/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketHeaderFilterStrategyTest.java
b/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketHeaderFilterStrategyTest.java
new file mode 100644
index 000000000000..3f2d7f1ffc26
--- /dev/null
+++
b/components/camel-vertx/camel-vertx-websocket/src/test/java/org/apache/camel/component/vertx/websocket/VertxWebsocketHeaderFilterStrategyTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.vertx.websocket;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class VertxWebsocketHeaderFilterStrategyTest {
+
+ private final VertxWebsocketHeaderFilterStrategy strategy = new
VertxWebsocketHeaderFilterStrategy();
+
+ @Test
+ void inboundCamelHeadersAreFiltered() {
+ assertTrue(strategy.applyFilterToExternalHeaders("CamelHttpUri",
"http://evil.example", null));
+ assertTrue(strategy.applyFilterToExternalHeaders("CamelFileName",
"../../etc/passwd", null));
+
assertTrue(strategy.applyFilterToExternalHeaders("CamelBeanMethodName",
"evilMethod", null));
+ }
+
+ @Test
+ void inboundLowercaseCamelHeadersAreFiltered() {
+ assertTrue(strategy.applyFilterToExternalHeaders("camelHttpUri",
"http://evil.example", null));
+ assertTrue(strategy.applyFilterToExternalHeaders("camelfilename",
"../../etc/passwd", null));
+ }
+
+ @Test
+ void outboundCamelHeadersAreFiltered() {
+ assertTrue(strategy.applyFilterToCamelHeaders("CamelHttpUri", "value",
null));
+ assertTrue(strategy.applyFilterToCamelHeaders("camelHttpUri", "value",
null));
+ }
+
+ @Test
+ void nonCamelHeadersPassThrough() {
+ assertFalse(strategy.applyFilterToExternalHeaders("Content-Type",
"application/json", null));
+ assertFalse(strategy.applyFilterToExternalHeaders("X-Request-Id",
"abc-123", null));
+ assertFalse(strategy.applyFilterToCamelHeaders("Content-Type",
"application/json", null));
+ }
+}
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
index a8e84e7196a0..7a9c89ea4ce2 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
@@ -317,3 +317,22 @@ aligning the component with the rest of the Camel
component catalog (`camel-kafk
`camel-coap`, `camel-google-pubsub`, ...). Routes that relied on passing
through these header
names from XMPP messages can supply a custom `headerFilterStrategy` to restore
the previous
behaviour.
+
+=== camel-vertx-websocket
+
+The `vertx-websocket` consumer now applies a `HeaderFilterStrategy` to the
WebSocket query and
+path parameters before mapping them into the Camel message headers. The new
default
+`VertxWebsocketHeaderFilterStrategy` filters headers starting with `Camel` /
`camel`
+(case-insensitive) in both the inbound and outbound directions, aligning the
component with the
+rest of the Camel component catalog (`camel-coap`, `camel-kafka`,
`camel-nats`, ...). A new
+`headerFilterStrategy` endpoint option is available; routes that relied on
receiving
+`Camel`-prefixed header names from WebSocket query or path parameters can
supply a custom
+`headerFilterStrategy` to restore the previous behaviour.
+
+=== camel-atmosphere-websocket
+
+The `atmosphere-websocket` consumer now applies the endpoint
`HeaderFilterStrategy` to the
+WebSocket query parameters before mapping them into the Camel message headers.
The inherited
+default `HttpHeaderFilterStrategy` filters headers starting with `Camel` /
`camel`
+(case-insensitive). Routes that relied on receiving `Camel`-prefixed header
names from WebSocket
+query parameters can supply a custom `headerFilterStrategy` to restore the
previous behaviour.
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/VertxWebsocketEndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/VertxWebsocketEndpointBuilderFactory.java
index 637db5f26220..ebc10c4f609e 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/VertxWebsocketEndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/VertxWebsocketEndpointBuilderFactory.java
@@ -531,6 +531,38 @@ public interface VertxWebsocketEndpointBuilderFactory {
doSetProperty("serverOptions", serverOptions);
return this;
}
+ /**
+ * To use a custom HeaderFilterStrategy to filter header to and from
+ * Camel message.
+ *
+ * The option is a:
+ * <code>org.apache.camel.spi.HeaderFilterStrategy</code> type.
+ *
+ * Group: advanced
+ *
+ * @param headerFilterStrategy the value to set
+ * @return the dsl builder
+ */
+ default AdvancedVertxWebsocketEndpointConsumerBuilder
headerFilterStrategy(org.apache.camel.spi.HeaderFilterStrategy
headerFilterStrategy) {
+ doSetProperty("headerFilterStrategy", headerFilterStrategy);
+ return this;
+ }
+ /**
+ * To use a custom HeaderFilterStrategy to filter header to and from
+ * Camel message.
+ *
+ * The option will be converted to a
+ * <code>org.apache.camel.spi.HeaderFilterStrategy</code> type.
+ *
+ * Group: advanced
+ *
+ * @param headerFilterStrategy the value to set
+ * @return the dsl builder
+ */
+ default AdvancedVertxWebsocketEndpointConsumerBuilder
headerFilterStrategy(String headerFilterStrategy) {
+ doSetProperty("headerFilterStrategy", headerFilterStrategy);
+ return this;
+ }
}
/**
@@ -812,6 +844,38 @@ public interface VertxWebsocketEndpointBuilderFactory {
doSetProperty("lazyStartProducer", lazyStartProducer);
return this;
}
+ /**
+ * To use a custom HeaderFilterStrategy to filter header to and from
+ * Camel message.
+ *
+ * The option is a:
+ * <code>org.apache.camel.spi.HeaderFilterStrategy</code> type.
+ *
+ * Group: advanced
+ *
+ * @param headerFilterStrategy the value to set
+ * @return the dsl builder
+ */
+ default AdvancedVertxWebsocketEndpointProducerBuilder
headerFilterStrategy(org.apache.camel.spi.HeaderFilterStrategy
headerFilterStrategy) {
+ doSetProperty("headerFilterStrategy", headerFilterStrategy);
+ return this;
+ }
+ /**
+ * To use a custom HeaderFilterStrategy to filter header to and from
+ * Camel message.
+ *
+ * The option will be converted to a
+ * <code>org.apache.camel.spi.HeaderFilterStrategy</code> type.
+ *
+ * Group: advanced
+ *
+ * @param headerFilterStrategy the value to set
+ * @return the dsl builder
+ */
+ default AdvancedVertxWebsocketEndpointProducerBuilder
headerFilterStrategy(String headerFilterStrategy) {
+ doSetProperty("headerFilterStrategy", headerFilterStrategy);
+ return this;
+ }
}
/**
@@ -960,6 +1024,38 @@ public interface VertxWebsocketEndpointBuilderFactory {
return (VertxWebsocketEndpointBuilder) this;
}
+ /**
+ * To use a custom HeaderFilterStrategy to filter header to and from
+ * Camel message.
+ *
+ * The option is a:
+ * <code>org.apache.camel.spi.HeaderFilterStrategy</code> type.
+ *
+ * Group: advanced
+ *
+ * @param headerFilterStrategy the value to set
+ * @return the dsl builder
+ */
+ default AdvancedVertxWebsocketEndpointBuilder
headerFilterStrategy(org.apache.camel.spi.HeaderFilterStrategy
headerFilterStrategy) {
+ doSetProperty("headerFilterStrategy", headerFilterStrategy);
+ return this;
+ }
+ /**
+ * To use a custom HeaderFilterStrategy to filter header to and from
+ * Camel message.
+ *
+ * The option will be converted to a
+ * <code>org.apache.camel.spi.HeaderFilterStrategy</code> type.
+ *
+ * Group: advanced
+ *
+ * @param headerFilterStrategy the value to set
+ * @return the dsl builder
+ */
+ default AdvancedVertxWebsocketEndpointBuilder
headerFilterStrategy(String headerFilterStrategy) {
+ doSetProperty("headerFilterStrategy", headerFilterStrategy);
+ return this;
+ }
}
public interface VertxWebsocketBuilders {