Message-ID: From: "davecramer (@davecramer)" To: "pgjdbc/pgjdbc" Date: Thu, 30 Apr 2026 11:18:20 +0000 Subject: [pgjdbc/pgjdbc] PR #4045: fix: append default non-proxy hosts when socksNonProxyHosts is set List-Id: X-GitHub-Additions: 29 X-GitHub-Author-Id: 406518 X-GitHub-Author-Login: davecramer X-GitHub-Base: master X-GitHub-Changed-Files: 2 X-GitHub-Commits: 1 X-GitHub-Deletions: 2 X-GitHub-Head-Branch: fix_hostspec_4044 X-GitHub-Head-SHA: 7f9e1a639dd4dfb188287dcec6b33e9d26a24e94 X-GitHub-Issue: 4045 X-GitHub-Merge-SHA: bd59eb2113fc486fd2345cf051bc022031b37507 X-GitHub-Merged-By: vlsi X-GitHub-Repo: pgjdbc/pgjdbc X-GitHub-State: merged X-GitHub-Type: pull_request X-GitHub-Url: https://github.com/pgjdbc/pgjdbc/pull/4045 Content-Type: text/plain; charset=utf-8 When socksNonProxyHosts is set by the system (e.g., macOS sets it to "local|*.local|169.254/16|*.169.254/16"), HostSpec used it as-is, completely replacing DEFAULT_NON_PROXY_HOSTS. Since 127.0.0.1 wasn't in the system-supplied list, HostSpec would pass an unresolved InetSocketAddress through the SOCKS proxy. But SocksSocketImpl (via DefaultProxySelector) always appends its built-in defaults to the property value, so it would bypass the proxy for 127.0.0.1 and try to connect directly with the still-unresolved address, causing an UnknownHostException. Align HostSpec with java.net.DefaultProxySelector by always merging DEFAULT_NON_PROXY_HOSTS with the user-supplied socksNonProxyHosts value instead of treating them as mutually exclusive. Fixes #4044 ### All Submissions: * [ ] Have you followed the guidelines in our [Contributing](https://github.com/pgjdbc/pgjdbc/blob/master/CONTRIBUTING.md) document? * [ ] Have you checked to ensure there aren't other open [Pull Requests](../../pulls) for the same update/change? ### New Feature Submissions: 1. [ ] Does your submission pass tests? 2. [ ] Does `./gradlew styleCheck` pass ? 3. [ ] Have you added your new test classes to an existing test suite in alphabetical order? ### Changes to Existing Features: * [ ] Does this break existing behaviour? If so please explain. * [ ] Have you added an explanation of what your changes do and why you'd like us to include them? * [ ] Have you written new tests for your core changes, as applicable? * [ ] Have you successfully run tests with your changes locally? diff --git a/pgjdbc/src/main/java/org/postgresql/util/HostSpec.java b/pgjdbc/src/main/java/org/postgresql/util/HostSpec.java index b7649ab42f..c37d1e975e 100644 --- a/pgjdbc/src/main/java/org/postgresql/util/HostSpec.java +++ b/pgjdbc/src/main/java/org/postgresql/util/HostSpec.java @@ -71,8 +71,15 @@ public Boolean shouldResolve() { } private Boolean matchesNonProxyHosts() { - String nonProxyHosts = System.getProperty("socksNonProxyHosts", DEFAULT_NON_PROXY_HOSTS); - if (nonProxyHosts == null || this.host.isEmpty()) { + String nonProxyHosts = System.getProperty("socksNonProxyHosts"); + if (nonProxyHosts == null || nonProxyHosts.isEmpty()) { + nonProxyHosts = DEFAULT_NON_PROXY_HOSTS; + } else { + // Align with java.net.DefaultProxySelector which always appends its + // built-in defaults (localhost, 127.*, etc.) to the user-supplied value. + nonProxyHosts = nonProxyHosts + "|" + DEFAULT_NON_PROXY_HOSTS; + } + if (this.host.isEmpty()) { return false; } diff --git a/pgjdbc/src/test/java/org/postgresql/test/util/HostSpecTest.java b/pgjdbc/src/test/java/org/postgresql/test/util/HostSpecTest.java index 7aad5bc88b..0614900d90 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/util/HostSpecTest.java +++ b/pgjdbc/src/test/java/org/postgresql/test/util/HostSpecTest.java @@ -86,6 +86,26 @@ void shouldResolveWithSocksNonProxyHostsNotMatching() throws Exception { assertFalse(hostSpec.shouldResolve()); } + @Test + void shouldResolveLocalhostIpWhenNonProxyHostsSetWithoutIt() throws Exception { + // Reproduces the macOS scenario: socksNonProxyHosts is set by the JVM + // (e.g. "local|*.local|169.254/16|*.169.254/16") but does NOT include 127.0.0.1. + // DefaultProxySelector always appends its built-in defaults (localhost, 127.*, etc.), + // so HostSpec must do the same to avoid an UnknownHostException from unresolved addresses. + System.setProperty("socksProxyHost", "127.0.0.1"); + System.setProperty("socksNonProxyHosts", "local|*.local|169.254/16|*.169.254/16"); + HostSpec hostSpec = new HostSpec("127.0.0.1", 5432); + assertTrue(hostSpec.shouldResolve()); + } + + @Test + void shouldResolveLocalhostWhenNonProxyHostsSetWithoutIt() throws Exception { + System.setProperty("socksProxyHost", "127.0.0.1"); + System.setProperty("socksNonProxyHosts", "local|*.local"); + HostSpec hostSpec = new HostSpec("localhost", 5432); + assertTrue(hostSpec.shouldResolve()); + } + @Test void shouldReturnEmptyLocalAddressBind() throws Exception { HostSpec hostSpec = new HostSpec("example.org", 5432);