From cb258b8e8d0f816e52574e1145285d7f1665c7dd Mon Sep 17 00:00:00 2001 From: Andrea Cosentino Date: Fri, 15 May 2026 12:16:58 +0200 Subject: [PATCH] CAMEL-23515: camel-nats - Use dedicated HeaderFilterStrategy aligned with sibling components (#23233) Introduce NatsHeaderFilterStrategy following the KafkaHeaderFilterStrategy / MailHeaderFilterStrategy shape (lowerCase=true, filter headers starting with Camel/camel/org.apache.camel. in both directions), and switch the default in NatsConfiguration to use it. Signed-off-by: Andrea Cosentino (cherry picked from commit be8aad96fa04f81d2b58884e27ba6755c9ad2718) --- .../component/nats/NatsConfiguration.java | 11 +++- .../nats/NatsHeaderFilterStrategy.java | 34 ++++++++++++ .../nats/NatsHeaderFilterStrategyTest.java | 53 +++++++++++++++++++ .../pages/camel-4x-upgrade-guide-4_14.adoc | 9 ++++ 4 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 components/camel-nats/src/main/java/org/apache/camel/component/nats/NatsHeaderFilterStrategy.java create mode 100644 components/camel-nats/src/test/java/org/apache/camel/component/nats/NatsHeaderFilterStrategyTest.java diff --git a/components/camel-nats/src/main/java/org/apache/camel/component/nats/NatsConfiguration.java b/components/camel-nats/src/main/java/org/apache/camel/component/nats/NatsConfiguration.java index 1f9d0d3fded81..85a3e0557940c 100644 --- a/components/camel-nats/src/main/java/org/apache/camel/component/nats/NatsConfiguration.java +++ b/components/camel-nats/src/main/java/org/apache/camel/component/nats/NatsConfiguration.java @@ -28,7 +28,6 @@ import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriParams; import org.apache.camel.spi.UriPath; -import org.apache.camel.support.DefaultHeaderFilterStrategy; import org.apache.camel.support.jsse.SSLContextParameters; import org.apache.camel.util.ObjectHelper; @@ -89,7 +88,7 @@ public class NatsConfiguration { @UriParam(label = "advanced") private boolean traceConnection; @UriParam(label = "advanced") - private HeaderFilterStrategy headerFilterStrategy = new DefaultHeaderFilterStrategy(); + private HeaderFilterStrategy headerFilterStrategy = new NatsHeaderFilterStrategy(); @UriParam(label = "common", defaultValue = "false") private boolean jetstreamEnabled = false; @UriParam(label = "common") @@ -97,6 +96,14 @@ public class NatsConfiguration { @UriParam(label = "advanced", defaultValue = "true") private boolean jetstreamAsync = true; + public NatsConfiguration copy() { + try { + return (NatsConfiguration) clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } + /** * URLs to one or more NAT servers. Use comma to separate URLs when specifying multiple servers. */ diff --git a/components/camel-nats/src/main/java/org/apache/camel/component/nats/NatsHeaderFilterStrategy.java b/components/camel-nats/src/main/java/org/apache/camel/component/nats/NatsHeaderFilterStrategy.java new file mode 100644 index 0000000000000..9997b3a666237 --- /dev/null +++ b/components/camel-nats/src/main/java/org/apache/camel/component/nats/NatsHeaderFilterStrategy.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.nats; + +import org.apache.camel.support.DefaultHeaderFilterStrategy; + +public class NatsHeaderFilterStrategy extends DefaultHeaderFilterStrategy { + + public NatsHeaderFilterStrategy() { + initialize(); + } + + protected void initialize() { + setLowerCase(true); + // filter headers begin with "Camel" or "org.apache.camel" + setOutFilterStartsWith(CAMEL_FILTER_STARTS_WITH); + setInFilterStartsWith(CAMEL_FILTER_STARTS_WITH); + } + +} diff --git a/components/camel-nats/src/test/java/org/apache/camel/component/nats/NatsHeaderFilterStrategyTest.java b/components/camel-nats/src/test/java/org/apache/camel/component/nats/NatsHeaderFilterStrategyTest.java new file mode 100644 index 0000000000000..96083045a0db8 --- /dev/null +++ b/components/camel-nats/src/test/java/org/apache/camel/component/nats/NatsHeaderFilterStrategyTest.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.nats; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class NatsHeaderFilterStrategyTest { + + private final NatsHeaderFilterStrategy strategy = new NatsHeaderFilterStrategy(); + + @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 6eaebe6945fda..63a7060ecbdf0 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 @@ -289,3 +289,12 @@ have been renamed accordingly: * `ccbTtl()` -> `couchbaseTtl()` * `ccbDdn()` -> `couchbaseDesignDocumentName()` * `ccbVn()` -> `couchbaseViewName()` + +=== camel-nats + +The default `headerFilterStrategy` is now a new `NatsHeaderFilterStrategy` that 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-kafka`, `camel-mail`, +`camel-coap`, `camel-google-pubsub`, ...). Routes that relied on passing through these header +names from NATS messages can supply a custom `headerFilterStrategy` to restore the previous +behaviour.