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

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


The following commit(s) were added to refs/heads/main by this push:
     new 5f58b90ff19e CAMEL-24424: camel-vertx-http - apply the outbound header 
filter on the REST producer (#26183)
5f58b90ff19e is described below

commit 5f58b90ff19e4360379e9dc5f611feedb294e9f7
Author: Andrea Cosentino <[email protected]>
AuthorDate: Tue Sep 8 13:30:13 2026 +0200

    CAMEL-24424: camel-vertx-http - apply the outbound header filter on the 
REST producer (#26183)
    
    VertxHttpRestHeaderFilterStrategy.applyFilterToCamelHeaders delegated to
    super.applyFilterToExternalHeaders, so it consulted the inbound filter while
    implementing the outbound direction. VertxHttpHeaderFilterStrategy only
    populates the out filter, so the common HTTP headers it installs were never
    applied on a REST producer, and message headers such as Content-Length,
    Transfer-Encoding, Host or Via were copied onto the outgoing request.
    
    The sibling REST strategies in camel-http-common, camel-netty-http and
    camel-undertow all delegate to the matching super method; vertx-http was the
    only one left with the mismatch.
    
    Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
    Co-authored-by: Claude Opus 4.8 <[email protected]>
---
 components/camel-vertx/camel-vertx-http/pom.xml    |  5 ++
 .../http/VertxHttpRestHeaderFilterStrategy.java    |  2 +-
 .../VertxHttpRestProducerHeaderFilterTest.java     | 81 ++++++++++++++++++++++
 .../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc    | 28 +++++---
 4 files changed, 106 insertions(+), 10 deletions(-)

diff --git a/components/camel-vertx/camel-vertx-http/pom.xml 
b/components/camel-vertx/camel-vertx-http/pom.xml
index 2bd09965d36b..fb7e6ec834ff 100644
--- a/components/camel-vertx/camel-vertx-http/pom.xml
+++ b/components/camel-vertx/camel-vertx-http/pom.xml
@@ -60,6 +60,11 @@
             <artifactId>camel-http</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-rest</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-undertow</artifactId>
diff --git 
a/components/camel-vertx/camel-vertx-http/src/main/java/org/apache/camel/component/vertx/http/VertxHttpRestHeaderFilterStrategy.java
 
b/components/camel-vertx/camel-vertx-http/src/main/java/org/apache/camel/component/vertx/http/VertxHttpRestHeaderFilterStrategy.java
index 87196d0869d0..8489945cf34f 100644
--- 
a/components/camel-vertx/camel-vertx-http/src/main/java/org/apache/camel/component/vertx/http/VertxHttpRestHeaderFilterStrategy.java
+++ 
b/components/camel-vertx/camel-vertx-http/src/main/java/org/apache/camel/component/vertx/http/VertxHttpRestHeaderFilterStrategy.java
@@ -32,7 +32,7 @@ public class VertxHttpRestHeaderFilterStrategy extends 
VertxHttpHeaderFilterStra
 
     @Override
     public boolean applyFilterToCamelHeaders(String headerName, Object 
headerValue, Exchange exchange) {
-        boolean answer = super.applyFilterToExternalHeaders(headerName, 
headerValue, exchange);
+        boolean answer = super.applyFilterToCamelHeaders(headerName, 
headerValue, exchange);
 
         return filterCheck(templateUri, queryParameters, headerName, answer);
     }
diff --git 
a/components/camel-vertx/camel-vertx-http/src/test/java/org/apache/camel/component/vertx/http/VertxHttpRestProducerHeaderFilterTest.java
 
b/components/camel-vertx/camel-vertx-http/src/test/java/org/apache/camel/component/vertx/http/VertxHttpRestProducerHeaderFilterTest.java
new file mode 100644
index 000000000000..fc6190cab638
--- /dev/null
+++ 
b/components/camel-vertx/camel-vertx-http/src/test/java/org/apache/camel/component/vertx/http/VertxHttpRestProducerHeaderFilterTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.http;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.Message;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+public class VertxHttpRestProducerHeaderFilterTest extends 
VertxHttpTestSupport {
+
+    @Test
+    public void testRestProducerAppliesTheOutboundFilter() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:input");
+        mock.expectedMessageCount(1);
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put("id", "123");
+        headers.put("Via", "1.1 rogue-proxy");
+        headers.put("Cache-Control", "no-cache");
+        headers.put("Content-Type", "application/json");
+        headers.put("X-Custom", "custom-value");
+
+        String out = template.requestBodyAndHeaders("direct:start", null, 
headers, String.class);
+        assertEquals("Hello World", out);
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        Message received = mock.getReceivedExchanges().get(0).getMessage();
+        // excluded on the outbound direction by the common HTTP filter set, 
so they must not reach the wire
+        assertNull(received.getHeader("Via"));
+        assertNull(received.getHeader("Cache-Control"));
+        // already consumed by the uri template, so it must not be sent as an 
HTTP header as well
+        assertNull(received.getHeader("id"));
+        // not filtered on either direction
+        assertEquals("custom-value", received.getHeader("X-Custom"));
+        // Content-Type is in the common HTTP filter set, but the producer 
sets it explicitly from the exchange
+        // content type before the filter loop runs, so it must still reach 
the server
+        assertEquals("application/json", received.getHeader("Content-Type"));
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                restConfiguration()
+                        .producerComponent("vertx-http")
+                        .host("localhost").port(getPort());
+
+                from("direct:start")
+                        .to("rest:get:foo/{id}");
+
+                from(getTestServerUri() + "/foo/123")
+                        .to("mock:input")
+                        .setBody(constant("Hello World"));
+            }
+        };
+    }
+}
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index 427ec6936a4a..5a9f1abf0e83 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -31,7 +31,6 @@ Only options whose value is a placeholder are affected, and 
only when running wi
 Camel Quarkus. If a component must not be stopped on reload, configure it 
programmatically rather than with a
 placeholder based property.
 
-
 === Apache Avro trusted packages
 
 Camel now uses Apache Avro 1.12.2. Avro validates classes resolved from schemas
@@ -1386,7 +1385,6 @@ camel.health.exposure-level = full
 The defaults are still registered as the lowest precedence property source, so 
all three settings are
 overridden by ordinary application configuration.
 
-
 ==== camel-debug-starter no longer opens a JMX connector by default
 
 `camel.debug.jmx-connector-enabled` now defaults to `false` instead of `true`. 
Adding
@@ -1415,7 +1413,6 @@ firewall.
 The `camel debug` command of Camel JBang is unaffected: it drives a Spring 
Boot application through the
 local CLI connector from `camel-cli-connector-starter`, not through JMX.
 
-
 ==== camel-spring-boot health check stack traces moved to the full exposure 
level
 
 The Camel health indicator added the full stack trace of a failed health check 
as `error.stacktrace` to the
@@ -1441,7 +1438,6 @@ camel.health.exposure-level = full
 Note that `full` also stops filtering the health check metadata out of the 
per-check data, so the output is
 more verbose than the previous default in other respects too.
 
-
 ==== camel-platform-http-starter deletes multipart uploads when the exchange 
completes
 
 Multipart file uploads are copied out of the servlet container into the 
servlet temporary directory so that they
@@ -1459,7 +1455,6 @@ the exchange has completed must opt out and delete the 
file itself:
 camel.component.platform-http.server.delete-uploaded-files-on-end=false
 ----
 
-
 ==== camel-platform-http-starter path variables follow the matched path
 
 Path variable headers are now taken from the path Spring matched the request 
against, instead of from
@@ -1492,7 +1487,6 @@ unaffected.
 `CamelHttpPath` (`Exchange.HTTP_PATH`) is unchanged: it still reports the raw 
request path with the
 servlet context-path removed.
 
-
 ==== camel-micrometer-starter bounds the uri tag
 
 The starter contributes the `uri` low cardinality tag of the 
`http.server.requests` metrics when
@@ -1520,7 +1514,6 @@ only for requests that resolve to a Camel consumer, and 
the tag value is now cap
 Dashboards and alerts that matched on the raw path of requests that are not 
served by Camel must use the Spring
 value instead, for example the mapped pattern `/actuator/health` of a Spring 
MVC endpoint.
 
-
 ==== camel-jasypt-starter defaults to PBEWITHHMACSHA256ANDAES_256
 
 `camel.component.jasypt.algorithm` now defaults to 
`PBEWITHHMACSHA256ANDAES_256` instead of `PBEWithMD5AndDES`.
@@ -1557,7 +1550,6 @@ The starter's usage documentation no longer shows the 
master password next to th
 the `sysenv:` or `sys:` prefixes of `camel.component.jasypt.password` to read 
it from the environment or a JVM
 system property, or inject it from an external secret store.
 
-
 ==== Starter configuration options that cannot be bound are reported
 
 The starters bind `camel.component.*`, `camel.dataformat.*` and 
`camel.language.*` onto the Camel component,
@@ -1610,7 +1602,6 @@ target class, where previously nothing was logged at all. 
Applications with hand
 therefore see new `WARN` lines at startup for options that have never been 
applied. The generated starters no
 longer use that path; they call 
`CamelPropertiesHelper.copyConfigurationProperties` instead.
 
-
 === camel-azure-storage-blob and camel-azure-storage-datalake
 
 Local downloads configured with `fileDir` now resolve existing filesystem path 
segments before checking
@@ -1743,3 +1734,22 @@ specific payload fields was silently given the whole 
payload.
 Both operations now use the header when it is present, and fall back to the 
`CamelQdrantWithPayload`
 boolean otherwise. A route that already sets the header starts receiving only 
the payload fields it
 selected; a route that does not set it is unaffected.
+
+=== camel-vertx-http - the REST producer applies the outbound header filter
+
+`VertxHttpRestHeaderFilterStrategy.applyFilterToCamelHeaders` delegated to
+`applyFilterToExternalHeaders`, so it consulted the inbound filter while 
implementing the outbound
+direction. The outbound filter that `VertxHttpHeaderFilterStrategy` installs 
was therefore never
+applied, and the sibling REST strategies in `camel-http-common`, 
`camel-netty-http` and
+`camel-undertow` all delegate to the matching method.
+
+A REST producer that resolves to `vertx-http` and does not configure its own 
`headerFilterStrategy`
+now filters the common HTTP headers on the outbound direction, as the other 
HTTP components already
+did. A message header named `Content-Length`, `Content-Type`, `Host`, 
`Cache-Control`, `Connection`,
+`Date`, `Pragma`, `Trailer`, `Transfer-Encoding`, `Upgrade`, `Via` or 
`Warning` is no longer copied
+onto the outgoing request; the `Content-Type` of the request is still taken 
from the exchange as
+before. Headers consumed by the URI template or the query parameters continue 
to be filtered, and a
+custom `headerFilterStrategy` is used as-is and is unaffected.
+
+Routes that relied on one of those headers reaching the wire must set it 
through the endpoint
+configuration or supply a `headerFilterStrategy` that permits it.

Reply via email to