Skip to content

Support setting the local address per connection with ConnectOptions - #6320

Open
jnbdz wants to merge 1 commit into
eclipse-vertx:masterfrom
SiteNetSoft:issue-2335-connect-local-address
Open

Support setting the local address per connection with ConnectOptions#6320
jnbdz wants to merge 1 commit into
eclipse-vertx:masterfrom
SiteNetSoft:issue-2335-connect-local-address

Conversation

@jnbdz

@jnbdz jnbdz commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Motivation

TCP based clients can only bind their connections to the local address configured at the client level; binding a given connection to a specific interface or port requires a dedicated client. This implements the approach discussed in #2335: the local address is a per-connection property, the client-level value is only a default.

Fixes #2335.

Changes

Following the steps listed in the issue:

  1. localAddress is removed from TcpClientConfig⚠️ note that TcpClientConfig#setLocalAddress was released in 5.1.x, so this is an API removal on 5.2; if you would rather keep it as @Deprecated and ignored for one release, I can adjust.
  2. the client default local address is now held by NetClientImpl and set by NetClientBuilder, from the legacy NetClientOptions#setLocalAddress(String) (NetClientBuilder#localAddress(ClientOptionsBase) does the mapping to an inet socket address with an ephemeral port).
  3. localAddress is added as a SocketAddress on ConnectOptions (domain socket addresses are rejected), and on HttpConnectOptions too since it does not extend ConnectOptions.
  4. at connect time, ConnectOptions#getLocalAddress() is used when set, otherwise the client default (which may be null).
  5. the resulting local address is set on the Bootstrap.

For the HTTP client, HttpClientImpl#connect(HttpConnectOptions) propagates the local address through HttpConnectParams to TcpHttpClientTransport, so an un-pooled connection can be bound to a local address; pooled requests keep using the client default. The QUIC transport is unchanged (it has its own configuration).

Legacy HTTP / WebSocket client local address was ignored

While wiring this I found that HttpClientOptions#setLocalAddress and WebSocketClientOptions#setLocalAddress were silently ignored on 5.x: HttpClientConfig(HttpClientOptions) goes through TcpClientConfig(ClientOptionsBase), which never copied the local address (only the NetClientOptions constructor did). With setLocalAddress("127.0.0.2") the server saw connections from 127.0.0.1. The existing HttpTest#testClientLocalAddress did not catch it because it binds to and asserts 127.0.0.1. This is fixed by passing the legacy options local address to NetClientBuilder in HttpClientBuilderInternal and in VertxImpl#createWebSocketClientImpl.

Tests

  • NetTest#testConnectOptionsLocalAddress: connect with ConnectOptions#setLocalAddress bound to a specific free port, assert the server sees that source port and NetSocket#localAddress() reports it.
  • NetTest#testConnectOptionsLocalAddressOverridesClientLocalAddress: the client is created with NetClientOptions#setLocalAddress, the connect options local address takes precedence.
  • Http1xTest#testConnectOptionsLocalAddress: same through HttpClient#connect(HttpConnectOptions).
  • Http1xTest#testClientOptionsLocalAddress: legacy HttpClientOptions#setLocalAddress("127.0.0.2") is honoured (skipped with Assume on platforms without that loopback address).
  • The existing NetTest#testClientLocalAddress / HttpTest#testClientLocalAddress keep passing.

Documentation: a paragraph and example in the TCP client section (connectingToAServerFromALocalAddress).

NetTest, Http1xTest, Http2Test, WebSocketTest, the proxy tests, SharedHttpClientTest and the net/options test packages pass locally.

Motivation:

TCP based clients can only bind their connections to the local address
configured at the client level. Binding a given connection to a local
address, e.g. a specific network interface or port, requires a dedicated
client. Fixes eclipse-vertx#2335.

In addition, the local address configured with the legacy
HttpClientOptions#setLocalAddress and WebSocketClientOptions#setLocalAddress
was ignored: TcpClientConfig(ClientOptionsBase) does not carry it and the
HTTP client is built from an HttpClientConfig.

Changes:

Add localAddress to ConnectOptions and HttpConnectOptions, when set the
connection is bound to it before connecting, otherwise the client default
local address is used, if any.

Remove localAddress from TcpClientConfig, the client default local address
is now held by NetClientImpl and set by NetClientBuilder, from the legacy
NetClientOptions, HttpClientOptions and WebSocketClientOptions.

Propagate the HttpConnectOptions local address to the TCP transport when
connecting an HttpClient connection.

Add NetClient and HTTP client tests binding connections to a specific local
port, and a test for the legacy HttpClientOptions local address, along with
a documentation example.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support setting local address when using tcp based clients

1 participant