Add authenticated forward-proxy support to HxClient#82
Open
ewels wants to merge 2 commits into
Open
Conversation
java.net.http.HttpClient ignores Authenticator.setDefault(), so proxy credentials only take effect when supplied via HttpClient.Builder.authenticator(). This adds first-class proxy support at the HxClient layer so every consumer benefits: - Add proxy(ProxySelector) and proxyAuthenticator(Authenticator) passthroughs on HxClient.Builder, forwarded to the inner HttpClient.Builder - Add HxProxyConfig helper that resolves HTTPS_PROXY/HTTP_PROXY/ ALL_PROXY and NO_PROXY (both cases), falling back to the https.proxyHost/http.proxyHost system properties, URL-decoding embedded user:pass@host:port credentials; its Authenticator releases credentials only for RequestorType.PROXY and the matching host/port - Auto-configure proxy and credentials from the environment when HxClient.newBuilder() is used with no explicit proxy; an explicitly supplied httpClient(...) is used verbatim - Make the token-refresh and anonymous Bearer token clients inherit the same proxy and authenticator via HxConfig - Integration tests against a local authenticating proxy covering plain HTTP (407 without credentials, 200 with) and the HTTPS CONNECT tunnelling case, with jdk.http.auth.tunneling.disabledSchemes cleared for the test JVM since the JDK strips Basic from CONNECT by default Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G5qZcbMECP5sixEQqivWXM
- Extract the proxy/authenticator application into a shared HxConfig.applyProxySettings() helper instead of repeating the same null-guarded block at the three HttpClient.Builder construction sites - Precompute the Proxy lists in HxProxyConfig.toProxySelector() so select() no longer allocates on every request - Drop the unused HxProxyConfig.getNoProxyHosts() accessor - Deduplicate the Authenticator.setDefault/disabledSchemes javadoc caveats, keeping the canonical text on HxProxyConfig Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G5qZcbMECP5sixEQqivWXM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
HxClientis the shared HTTP client for Nextflow (SCM pulls, plugin downloads, registry, Tower) and Wave. Users behind an authenticating corporate proxy currently cannot use it: routing works viaProxySelector.getDefault(), but there is no way to supply proxy credentials. Fixing it at this shared layer means every consumer benefits.Related to nextflow-io/nextflow#7305.
The
Authenticator.setDefaultlimitationjava.net.http.HttpClientignoresAuthenticator.setDefault(...)— proxy credentials only take effect when the authenticator is supplied viaHttpClient.Builder.authenticator(...). Verified against a local authenticating proxy: default-authenticator gives 407, builder-authenticator gives 200. This is why the fix must live in the client builder rather than in application bootstrap code.Changes
HxClient.Builder.proxy(ProxySelector)and.proxyAuthenticator(Authenticator)passthroughs, forwarded to the innerHttpClient.Builder.HxProxyConfig(new): resolvesHTTPS_PROXY/HTTP_PROXY/ALL_PROXYandNO_PROXY(upper and lower case), falling back to thehttps.proxyHost/http.proxyHostsystem properties. URL-decodes embeddeduser:pass@host:portcredentials. ItsAuthenticatorreleases credentials only forRequestorType.PROXYwith matching host/port — never to origin servers (mirrors Nextflow'sProxyConfig). ItsProxySelectorhonoursNO_PROXYand always bypasses loopback targets, consistent with the JDK defaulthttp.nonProxyHosts.HxClient.newBuilder()with no explicit proxy resolves the configuration from the environment automatically. An explicitly suppliedhttpClient(...)is used verbatim; with no proxy configured in the environment, behaviour is unchanged.HxTokenManager) and anonymous Bearer token retrieval inherit the same proxy and authenticator viaHxConfig, instead of a bareHttpClient.newHttpClient().The
disabledSchemesdependencyThe JDK strips the Basic scheme from HTTPS CONNECT tunnelling by default (
jdk.http.auth.tunneling.disabledSchemes=Basicin$JAVA_HOME/conf/net.properties). Basic proxy authentication for HTTPS traffic therefore also requires running the JVM with-Djdk.http.auth.tunneling.disabledSchemes=. This is documented in the README and javadoc, and set for this module's test JVM inbuild.gradle.Tests
./gradlew :lib-httpx:testpasses (201 tests). New coverage:MockAuthProxyServer) that returns 407 withoutProxy-Authorizationand 200 with the correct Basic credentials: HxClient succeeds when credentials are supplied and gets 407 when they are absent.disabledSchemescleared for the test JVM).NO_PROXYmatching, and authenticator scoping (proxy-only, host/port match).🤖 Generated with Claude Code
https://claude.ai/code/session_01G5qZcbMECP5sixEQqivWXM
Generated by Claude Code