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.