This is an automated email from the ASF dual-hosted git repository. acosentino 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 e8805e4 CAMEL-13116 - DefaultHeaderFilterStrategy match action configurable e8805e4 is described below commit e8805e4d0760318b7ea2ecafff0fc3607e5551e5 Author: Aniol Massana <aniol.mass...@corusconsulting.com> AuthorDate: Fri Feb 8 12:25:03 2019 +0100 CAMEL-13116 - DefaultHeaderFilterStrategy match action configurable * filterOnMatch parameter added * test cases * documentation --- .../impl/DefaultHeaderFilterStrategyTest.java | 29 ++++++- .../camel/support/DefaultHeaderFilterStrategy.java | 95 +++++++++++++--------- ...-avoid-sending-some-or-all-message-headers.adoc | 55 ++++++++++++- 3 files changed, 133 insertions(+), 46 deletions(-) diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultHeaderFilterStrategyTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultHeaderFilterStrategyTest.java index 4bd1333..40d00a0 100644 --- a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultHeaderFilterStrategyTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultHeaderFilterStrategyTest.java @@ -36,9 +36,12 @@ public class DefaultHeaderFilterStrategyTest extends ContextTestSupport { comp.setLowerCase(true); assertEquals(true, comp.isLowerCase()); - + comp.setCaseInsensitive(true); assertEquals(true, comp.isCaseInsensitive()); + + comp.setFilterOnMatch(false); + assertEquals(false, comp.isFilterOnMatch()); } @Test @@ -94,12 +97,30 @@ public class DefaultHeaderFilterStrategyTest extends ContextTestSupport { assertFalse(comp.applyFilterToCamelHeaders("bar", 123, exchange)); assertTrue(comp.applyFilterToCamelHeaders("foo", "cheese", exchange)); } - + + @Test + public void testOutReverseFilterDefaultHeaderFilterStrategy() { + DefaultHeaderFilterStrategy comp = new DefaultHeaderFilterStrategy(); + + comp.setFilterOnMatch(false); + + Set<String> set = new HashSet<>(); + set.add("foo"); + comp.setOutFilter(set); + + Exchange exchange = new DefaultExchange(context); + exchange.getIn().setHeader("bar", 123); + exchange.getIn().setHeader("foo", "cheese"); + + assertTrue(comp.applyFilterToCamelHeaders("bar", 123, exchange)); + assertFalse(comp.applyFilterToCamelHeaders("foo", "cheese", exchange)); + } + @Test public void testCaseInsensitiveHeaderNameDoFilterDefaultHeaderFilterStrategy() { DefaultHeaderFilterStrategy comp = new DefaultHeaderFilterStrategy(); comp.setCaseInsensitive(true); - + Set<String> set = new HashSet<>(); set.add("Content-Type"); comp.setOutFilter(set); @@ -111,5 +132,5 @@ public class DefaultHeaderFilterStrategyTest extends ContextTestSupport { assertTrue(comp.applyFilterToCamelHeaders("content-type", "application/xml", exchange)); assertTrue(comp.applyFilterToCamelHeaders("Content-Type", "application/json", exchange)); } - + } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/DefaultHeaderFilterStrategy.java b/core/camel-support/src/main/java/org/apache/camel/support/DefaultHeaderFilterStrategy.java index 6dbc7cd..d5b29b8 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/DefaultHeaderFilterStrategy.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/DefaultHeaderFilterStrategy.java @@ -27,18 +27,18 @@ import org.apache.camel.spi.HeaderFilterStrategy; /** * The default header filtering strategy. Users can configure filter by * setting filter set and/or setting a regular expression. Subclass can - * add extended filter logic in + * add extended filter logic in * {@link #extendedFilter(org.apache.camel.spi.HeaderFilterStrategy.Direction, String, Object, org.apache.camel.Exchange)} - * + * * Filters are associated with directions (in or out). "In" direction is * referred to propagating headers "to" Camel message. The "out" direction * is opposite which is referred to propagating headers from Camel message * to a native message like JMS and CXF message. You can see example of - * DefaultHeaderFilterStrategy are being extended and invoked in camel-jms + * DefaultHeaderFilterStrategy are being extended and invoked in camel-jms * and camel-cxf components. */ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy { - + private Set<String> inFilter; private Pattern inFilterPattern; @@ -48,7 +48,8 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy { private boolean lowerCase; private boolean allowNullValues; private boolean caseInsensitive; - + private boolean filterOnMatch = true; // defaults to the previous behaviour + public boolean applyFilterToCamelHeaders(String headerName, Object headerValue, Exchange exchange) { return doFiltering(Direction.OUT, headerName, headerValue, exchange); } @@ -60,14 +61,14 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy { /** * Gets the "out" direction filter set. The "out" direction is referred to * copying headers from a Camel message to an external message. - * + * * @return a set that contains header names that should be excluded. */ public Set<String> getOutFilter() { if (outFilter == null) { outFilter = new HashSet<>(); } - + return outFilter; } @@ -85,8 +86,8 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy { * Gets the "out" direction filter regular expression {@link Pattern}. The * "out" direction is referred to copying headers from Camel message to * an external message. If the pattern matches a header, the header will - * be filtered out. - * + * be filtered out. + * * @return regular expression filter pattern */ public String getOutFilterPattern() { @@ -97,8 +98,8 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy { * Sets the "out" direction filter regular expression {@link Pattern}. The * "out" direction is referred to copying headers from Camel message to * an external message. If the pattern matches a header, the header will - * be filtered out. - * + * be filtered out. + * * @param value regular expression filter pattern */ public void setOutFilterPattern(String value) { @@ -108,11 +109,11 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy { outFilterPattern = Pattern.compile(value); } } - + /** * Gets the "in" direction filter set. The "in" direction is referred to * copying headers from an external message to a Camel message. - * + * * @return a set that contains header names that should be excluded. */ public Set<String> getInFilter() { @@ -136,20 +137,20 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy { * Gets the "in" direction filter regular expression {@link Pattern}. The * "in" direction is referred to copying headers from an external message * to a Camel message. If the pattern matches a header, the header will - * be filtered out. - * + * be filtered out. + * * @return regular expression filter pattern */ public String getInFilterPattern() { return inFilterPattern == null ? null : inFilterPattern.pattern(); } - + /** * Sets the "in" direction filter regular expression {@link Pattern}. The * "in" direction is referred to copying headers from an external message * to a Camel message. If the pattern matches a header, the header will - * be filtered out. - * + * be filtered out. + * * @param value regular expression filter pattern */ public void setInFilterPattern(String value) { @@ -169,7 +170,7 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy { public boolean isLowerCase() { return lowerCase; } - + /** * Sets the isLowercase property which is a boolean to determine * whether header names should be converted to lower case before @@ -182,11 +183,11 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy { /** * Gets the caseInsensitive property which is a boolean to determine - * whether header names should be case insensitive when checking it + * whether header names should be case insensitive when checking it * with the filter set. * It does not affect filtering using regular expression pattern. - * - * @return <tt>true</tt> if header names is case insensitive. + * + * @return <tt>true</tt> if header names is case insensitive. */ public boolean isCaseInsensitive() { return caseInsensitive; @@ -194,66 +195,84 @@ public class DefaultHeaderFilterStrategy implements HeaderFilterStrategy { /** * Sets the caseInsensitive property which is a boolean to determine - * whether header names should be case insensitive when checking it + * whether header names should be case insensitive when checking it * with the filter set. * It does not affect filtering using regular expression pattern, - * + * * @param caseInsensitive <tt>true</tt> if header names is case insensitive. */ public void setCaseInsensitive(boolean caseInsensitive) { this.caseInsensitive = caseInsensitive; } - + public boolean isAllowNullValues() { return allowNullValues; } - + public void setAllowNullValues(boolean value) { allowNullValues = value; - } + } + + public boolean isFilterOnMatch() { + return filterOnMatch; + } + + /** + * Sets the filterOnMatch property which is a boolean to determine + * what to do when a pattern or filter set is matched. + * + * When set to true, a match will filter out the header. This is the default value for backwards compatibility. + * + * When set to false, the pattern or filter will indicate that the header must be kept; anything not matched will be filtered out. + * + * @param filterOnMatch <tt>true</tt> if a match filters out the header. + */ + public void setFilterOnMatch(boolean filterOnMatch) { + this.filterOnMatch = filterOnMatch; + } protected boolean extendedFilter(Direction direction, String key, Object value, Exchange exchange) { - return false; + return !filterOnMatch; } private boolean doFiltering(Direction direction, String headerName, Object headerValue, Exchange exchange) { if (headerName == null) { return true; } - + if (headerValue == null && !allowNullValues) { return true; } - + Pattern pattern = null; Set<String> filter = null; - + if (Direction.OUT == direction) { pattern = outFilterPattern; - filter = outFilter; + filter = outFilter; } else if (Direction.IN == direction) { pattern = inFilterPattern; filter = inFilter; } - + if (pattern != null && pattern.matcher(headerName).matches()) { - return true; + return filterOnMatch; } - + if (filter != null) { if (isCaseInsensitive()) { for (String filterString : filter) { if (filterString.equalsIgnoreCase(headerName)) { - return true; + return filterOnMatch; } } } else if (isLowerCase()) { if (filter.contains(headerName.toLowerCase(Locale.ENGLISH))) { - return true; + return filterOnMatch; } } else { if (filter.contains(headerName)) { - return true; + return filterOnMatch; } } } diff --git a/docs/user-manual/en/faq/how-to-avoid-sending-some-or-all-message-headers.adoc b/docs/user-manual/en/faq/how-to-avoid-sending-some-or-all-message-headers.adoc index be9f6b4..6a3e156 100644 --- a/docs/user-manual/en/faq/how-to-avoid-sending-some-or-all-message-headers.adoc +++ b/docs/user-manual/en/faq/how-to-avoid-sending-some-or-all-message-headers.adoc @@ -69,7 +69,54 @@ An alternative is that some of the Camel link:../component.adoc[Components] supports configuring a custom header filter strategy. This allows you to implement the -`org.apache.camel.spi.HeaderFilterStrategy` interface, where you can -filter unwanted headers. -Though it's often easier to use the `removeHeaders` in the Camel route as -shown above. +`org.apache.camel.spi.HeaderFilterStrategy` interface, where one can +filter unwanted headers from the communication while not removing them from the +Exchange. Though it's often easier to use the `removeHeaders` in the Camel route +as shown above. + +Camel core offers a default filter strategy implementation, the +DefaultHeaderFilterStrategy class, to which one can provide a regular expression +pattern or a set of header names to be filtered out. + +[source,xml] +---- +<bean class="org.apache.camel.impl.DefaultHeaderFilterStrategy" id="myFilter"> + <property name="outFilter"> + <set> + <value>unwantedHeaderName</value> + </set> + </property> +</bean> +... +<setHeader headerName="allowedHeaderName"><constant>some metadata</constant></setHeader> +<setHeader headerName="unwantedHeaderName"><constant>some private data</constant></setHeader> +<to id="publish" uri="activemq:queue:destinationName?headerFilterStrategy=#myFilter"/> +<log message="${header.unwantedHeaderName}"/> +---- + +The destination queue would receive a JMS message with the allowedHeaderName as +JMS property. If the queue messages are consumed by a Camel route, then the +exchange will have the allowedHeaderName as a header. The log would print "some +private data" since the header has only been filtered out from the producer +endpoint, but not removed from the Exchange. + +[[Howtoavoidsendingsomeorallmessageheaders-SelectingTheAcceptedHeaders]] +==== Selecting the accepted headers + +The more steps a route has, more headers tend to be present in the exchange. +When the number of headers is large, undetermined, or one can't know in advance +which headers must be filtered out, it is desirable not to deliver by default +the headers to the destination endpoint. + +In this case, one can filter out everything and selectively send only certain +headers to the destination endpoint. The DefaultHeaderFilterStrategy behavior +can be reversed so only certain headers are accepted through the filterOnMatch +property. + +[source,xml] +---- +<bean class="org.apache.camel.impl.DefaultHeaderFilterStrategy" id="myFilter"> + <property name="filterOnMatch" value="false" /> + ... +</bean> +----