This is an automated email from the ASF dual-hosted git repository. orpiske pushed a commit to branch camel-4.18.x in repository https://gitbox.apache.org/repos/asf/camel.git
commit d791aa48d2c679878e8b95367f2efe7f556da0b4 Author: Otavio Rodolfo Piske <[email protected]> AuthorDate: Fri Oct 23 16:05:27 2026 +0200 CAMEL-26108: camel-avro-rpc - the component should configure all options on the endpoint Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> (cherry picked from commit 55b266d9403f6d35e08752726156a8cf9bdc4387) --- .../apache/camel/component/avro/AvroListener.java | 2 +- .../component/avro/AvroHttpConsumerHostTest.java | 80 ++++++++++++++++++++++ .../component/avro/spi/JettyHttpServerFactory.java | 5 ++ .../avro/spi/AvroRpcHttpServerFactory.java | 19 +++++ .../ROOT/pages/camel-4x-upgrade-guide-4_18.adoc | 9 +++ 5 files changed, 114 insertions(+), 1 deletion(-) diff --git a/components/camel-avro-rpc/camel-avro-rpc-component/src/main/java/org/apache/camel/component/avro/AvroListener.java b/components/camel-avro-rpc/camel-avro-rpc-component/src/main/java/org/apache/camel/component/avro/AvroListener.java index 8e5dacbbec51..b006335f2037 100644 --- a/components/camel-avro-rpc/camel-avro-rpc-component/src/main/java/org/apache/camel/component/avro/AvroListener.java +++ b/components/camel-avro-rpc/camel-avro-rpc-component/src/main/java/org/apache/camel/component/avro/AvroListener.java @@ -88,7 +88,7 @@ public class AvroListener { .newInstance("avro-rpc-http-server-factory", AvroRpcHttpServerFactory.class) .orElseThrow(() -> new IllegalStateException( "AvroRpcHttpServerFactory is neither set on this endpoint neither found in Camel Registry or FactoryFinder.")); - return factory.create(responder, configuration.getPort()); + return factory.create(responder, configuration.getHost(), configuration.getPort()); } else if (AVRO_NETTY_TRANSPORT.equalsIgnoreCase(configuration.getTransport().name())) { return new NettyServer(responder, new InetSocketAddress(configuration.getHost(), configuration.getPort())); } else { diff --git a/components/camel-avro-rpc/camel-avro-rpc-component/src/test/java/org/apache/camel/component/avro/AvroHttpConsumerHostTest.java b/components/camel-avro-rpc/camel-avro-rpc-component/src/test/java/org/apache/camel/component/avro/AvroHttpConsumerHostTest.java new file mode 100644 index 000000000000..53253fc2d534 --- /dev/null +++ b/components/camel-avro-rpc/camel-avro-rpc-component/src/test/java/org/apache/camel/component/avro/AvroHttpConsumerHostTest.java @@ -0,0 +1,80 @@ +/* + * 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.avro; + +import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.Socket; +import java.net.SocketException; + +import org.apache.camel.builder.RouteBuilder; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * The http consumer listens on the host of the endpoint, as the netty consumer does. + */ +public class AvroHttpConsumerHostTest extends AvroTestSupport { + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("avro:http:127.0.0.1:" + avroPort + + "/getName?protocolClassName=org.apache.camel.avro.test.TestReflection") + .setBody(constant("Camel")); + } + }; + } + + @Test + public void testListensOnConfiguredHostOnly() throws Exception { + InetAddress other = findNonLoopbackAddress(); + assumeTrue(other != null, "No non-loopback IPv4 address available"); + + assertDoesNotThrow(() -> connect(InetAddress.getByName("127.0.0.1"))); + assertThrows(IOException.class, () -> connect(other)); + } + + private void connect(InetAddress address) throws IOException { + try (Socket socket = new Socket()) { + socket.connect(new InetSocketAddress(address, avroPort), 2000); + } + } + + private static InetAddress findNonLoopbackAddress() throws SocketException { + return NetworkInterface.networkInterfaces() + .filter(nic -> { + try { + return nic.isUp() && !nic.isLoopback(); + } catch (SocketException e) { + return false; + } + }) + .flatMap(NetworkInterface::inetAddresses) + .filter(address -> address instanceof Inet4Address && !address.isLoopbackAddress()) + .findFirst() + .orElse(null); + } +} diff --git a/components/camel-avro-rpc/camel-avro-rpc-jetty/src/main/java/org/apache/camel/component/avro/spi/JettyHttpServerFactory.java b/components/camel-avro-rpc/camel-avro-rpc-jetty/src/main/java/org/apache/camel/component/avro/spi/JettyHttpServerFactory.java index 0e428fc559f7..1a5c905dd6b5 100644 --- a/components/camel-avro-rpc/camel-avro-rpc-jetty/src/main/java/org/apache/camel/component/avro/spi/JettyHttpServerFactory.java +++ b/components/camel-avro-rpc/camel-avro-rpc-jetty/src/main/java/org/apache/camel/component/avro/spi/JettyHttpServerFactory.java @@ -32,4 +32,9 @@ public class JettyHttpServerFactory implements AvroRpcHttpServerFactory { public Server create(SpecificResponder responder, int port) throws IOException { return new HttpServer(responder, port); } + + @Override + public Server create(SpecificResponder responder, String host, int port) throws IOException { + return new HttpServer(responder, host, port); + } } diff --git a/components/camel-avro-rpc/camel-avro-rpc-spi/src/main/java/org/apache/camel/component/avro/spi/AvroRpcHttpServerFactory.java b/components/camel-avro-rpc/camel-avro-rpc-spi/src/main/java/org/apache/camel/component/avro/spi/AvroRpcHttpServerFactory.java index c53fde1fcffe..136d5052096a 100644 --- a/components/camel-avro-rpc/camel-avro-rpc-spi/src/main/java/org/apache/camel/component/avro/spi/AvroRpcHttpServerFactory.java +++ b/components/camel-avro-rpc/camel-avro-rpc-spi/src/main/java/org/apache/camel/component/avro/spi/AvroRpcHttpServerFactory.java @@ -25,5 +25,24 @@ import org.apache.avro.ipc.specific.SpecificResponder; */ public interface AvroRpcHttpServerFactory { + /** + * Creates a server that listens on the given port on all interfaces. + */ Server create(SpecificResponder responder, int port) throws Exception; + + /** + * Creates a server that listens on the given host and port. + * + * The default implementation ignores the host and calls {@link #create(SpecificResponder, int)}, so an + * implementation should override it to listen on the host the endpoint is configured with. + * + * @param responder the responder + * @param host the host or address to listen on + * @param port the port to listen on + * @return the server + * @since 4.18.6 + */ + default Server create(SpecificResponder responder, String host, int port) throws Exception { + return create(responder, port); + } } diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc index 19a7f0f65253..9333e7beb726 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_18.adoc @@ -1875,3 +1875,12 @@ now refuses to send a request path, query or header value that contains a contro framing, are still allowed. Routes that put a percent-encoded control character (such as `%0D%0A`) into the `CamelHttpPath` or `CamelHttpQuery` header, which the producer decodes before building the request, are the ones most likely to be affected. + +=== camel-avro-rpc - the http consumer listens on the host of the endpoint + +The `avro:http` consumer now uses the host of the endpoint URI (`avro:http:[host]:[port]`) for its HTTP server, as the `avro:netty` consumer does. + +Use `0.0.0.0` as the host to accept connections on all network interfaces. + +`AvroRpcHttpServerFactory` has a new method `create(SpecificResponder, String, int)` that receives the host. A custom factory should implement it. +
