Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add enableInetAddressCreateUnresolved option
  • Loading branch information
bartosz822 committed Nov 5, 2025
commit 45da71daef8ab17b02ddde1aef3ee6133d7fc2c8
29 changes: 29 additions & 0 deletions src/main/java/io/nats/client/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,12 @@ public class Options {
*/
public static final String PROP_FAST_FALLBACK = PFX + "fast.fallback";

/**
* Property used to enable InetSocketAddress.createUnresolved for proxied connections.
* {@link Builder#enableInetAddressCreateUnresolved() enableInetAddressCreateUnresolved}.
*/
public static final String PROP_ENABLE_INET_ADDRESS_CREATE_UNRESOLVED = PFX + "inet.address.create.unresolved";

// ----------------------------------------------------------------------------------------------------
// PROTOCOL CONNECT OPTION CONSTANTS
// ----------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -714,6 +720,7 @@ public class Options {
private final List<java.util.function.Consumer<HttpRequest>> httpRequestInterceptors;
private final Proxy proxy;
private final boolean enableFastFallback;
private final boolean enableInetAddressCreateUnresolved;

static class DefaultThreadFactory implements ThreadFactory {
final String name;
Expand Down Expand Up @@ -865,6 +872,7 @@ public static class Builder {
private String tlsAlgorithm = DEFAULT_TLS_ALGORITHM;
private String credentialPath;
private boolean enableFastFallback = false;
private boolean enableInetAddressCreateUnresolved = false;

/**
* Constructs a new Builder with the default values.
Expand Down Expand Up @@ -984,6 +992,7 @@ public Builder properties(Properties props) {
booleanProperty(props, PROP_USE_DISPATCHER_WITH_EXECUTOR, b -> this.useDispatcherWithExecutor = b);
booleanProperty(props, PROP_FORCE_FLUSH_ON_REQUEST, b -> this.forceFlushOnRequest = b);
booleanProperty(props, PROP_FAST_FALLBACK, b -> this.enableFastFallback = b);
booleanProperty(props, PROP_ENABLE_INET_ADDRESS_CREATE_UNRESOLVED, b -> this.enableInetAddressCreateUnresolved = b);

classnameProperty(props, PROP_SERVERS_POOL_IMPLEMENTATION_CLASS, o -> this.serverPool = (ServerPool) o);
classnameProperty(props, PROP_DISPATCHER_FACTORY_CLASS, o -> this.dispatcherFactory = (DispatcherFactory) o);
Expand Down Expand Up @@ -1889,6 +1898,16 @@ public Builder enableFastFallback() {
return this;
}

/**
* Whether to enable InetSocketAddress.createUnresolved for proxied connections.
* This is useful for backward compatibility and when hostname resolution should be deferred.
* @return the Builder for chaining
*/
public Builder enableInetAddressCreateUnresolved() {
this.enableInetAddressCreateUnresolved = true;
return this;
}

/**
* Build an Options object from this Builder.
*
Expand Down Expand Up @@ -2114,6 +2133,7 @@ public Builder(Options o) {
this.serverPool = o.serverPool;
this.dispatcherFactory = o.dispatcherFactory;
this.enableFastFallback = o.enableFastFallback;
this.enableInetAddressCreateUnresolved = o.enableInetAddressCreateUnresolved;
}
}

Expand Down Expand Up @@ -2186,6 +2206,7 @@ private Options(Builder b) {
this.serverPool = b.serverPool;
this.dispatcherFactory = b.dispatcherFactory;
this.enableFastFallback = b.enableFastFallback;
this.enableInetAddressCreateUnresolved = b.enableInetAddressCreateUnresolved;
}

// ----------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -2729,6 +2750,14 @@ public boolean isEnableFastFallback() {
return enableFastFallback;
}

/**
* Whether InetSocketAddress.createUnresolved is enabled for proxied connections
* @return the flag
*/
public boolean isEnableInetAddressCreateUnresolved() {
return enableInetAddressCreateUnresolved;
}

public URI createURIForServer(String serverURI) throws URISyntaxException {
return new NatsUri(serverURI).getUri();
}
Expand Down
9 changes: 6 additions & 3 deletions src/main/java/io/nats/client/impl/SocketDataPort.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,12 @@ public void connect(@NonNull NatsConnection conn, @NonNull NatsUri nuri, long ti
socket = connectToFastestIp(options, host, port, (int) timeout);
} else {
socket = createSocket(options);
boolean shouldCreateUnresolvedInetAddress = (options.isNoResolveHostnames() && !nuri.hostIsIpAddress() && (options.getProxy() != null));
InetSocketAddress inetSocketAddress = shouldCreateUnresolvedInetAddress ?
InetSocketAddress.createUnresolved(host, port) : new InetSocketAddress(host, port);
InetSocketAddress inetSocketAddress;
if (options.isEnableInetAddressCreateUnresolved() && !nuri.hostIsIpAddress()) {
inetSocketAddress = InetSocketAddress.createUnresolved(host, port);
} else {
inetSocketAddress = new InetSocketAddress(host, port);
}
socket.connect(inetSocketAddress, (int) timeout);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public void shutdown() throws IOException {
* This allows proxies with domain whitelisting to work correctly.
*/
@Test
public void testProxyReceivesDomainNameWithNoResolveHostnames() throws Exception {
public void testProxyReceivesDomainNameWithEnableInetAddressCreateUnresolved() throws Exception {
testProxyHostnameResolution(
true, // enableNoResolveHostnames
"nats://localhost:4222",
Expand All @@ -146,15 +146,15 @@ public void testProxyReceivesDomainNameWithNoResolveHostnames() throws Exception
}

/**
* Test that WITHOUT noResolveHostnames(), the proxy receives an IP address instead
* Test that WITHOUT isEnableInetAddressCreateUnresolved(), the proxy receives an IP address instead
* of the domain name. This demonstrates the bug that was fixed.
*
* When noResolveHostnames() is NOT set and a proxy is configured, the hostname
* When isEnableInetAddressCreateUnresolved() is NOT set and a proxy is configured, the hostname
* gets resolved to an IP address before being sent to the proxy. This breaks
* proxies with domain name whitelisting.
*/
@Test
public void testProxyReceivesIpAddressWithoutNoResolveHostnames() throws Exception {
public void testProxyReceivesIpAddressWithoutEnableInetAddressCreateUnresolved() throws Exception {
testProxyHostnameResolution(
false, // disableNoResolveHostnames
"nats://localhost:4222",
Expand All @@ -165,11 +165,11 @@ public void testProxyReceivesIpAddressWithoutNoResolveHostnames() throws Excepti
/**
* Helper method to test proxy hostname resolution behavior.
*
* @param useNoResolveHostnames Whether to enable noResolveHostnames() option
* @param useEnableInetAddressCreateUnresolved Whether to enable isEnableInetAddressCreateUnresolved() option
* @param targetUri The URI to connect to
* @param expectIpAddress True if expecting proxy to receive an IP, false for hostname
*/
private void testProxyHostnameResolution(boolean useNoResolveHostnames, String targetUri,
private void testProxyHostnameResolution(boolean useEnableInetAddressCreateUnresolved, String targetUri,
boolean expectIpAddress)
throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(3);
Expand All @@ -182,8 +182,8 @@ private void testProxyHostnameResolution(boolean useNoResolveHostnames, String t
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", proxyServer.getPort())))
.noReconnect();

if (useNoResolveHostnames) {
optionsBuilder.noResolveHostnames();
if (useEnableInetAddressCreateUnresolved) {
optionsBuilder.enableInetAddressCreateUnresolved();
}

Options options = optionsBuilder.build();
Expand Down
Loading