feat: add a custom proxyAgent option to the Node server SDK#1438
Conversation
Support SOCKS proxies via LDProxyOptions.scheme. Setting scheme to one of socks, socks4, socks4a, socks5, or socks5h routes both fetch and event-source traffic through a SOCKS proxy using socks-proxy-agent; a single agent handles both http and https targets. The proxy address is built as a URL so its username/password setters percent-encode the credentials, which socks-proxy-agent then decodes, so an auth password may safely contain characters such as ':'. TLS agent options are forwarded to the SOCKS agent for https targets. Adds end-to-end tests (polling, streaming, and username/password auth) backed by a minimal RFC 1928/1929 SOCKS5 test server.
|
Heads up on CI: the failing checks are all example-app smoke tests ( All SDK build/test checks relevant to this change pass, including |
|
Hey @bradbunce thanks for the contribution. I will need to speak with the team to see if we agree that this is a broad SDK feature that we want to pursue. UPDATE |
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build the SOCKS proxy address with formatUrl (the same handling the HTTP proxy path uses) so IPv6 literal hosts are bracketed and a missing port is omitted rather than appended as the literal string 'undefined'. Also strip the brackets off the parsed proxy host, since socks-proxy-agent derives it from URL.hostname and hands the bracketed literal to net.connect, which cannot resolve it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per maintainer feedback, expose a Node-specific `proxyAgent` option instead of teaching the SDK about SOCKS schemes. Applications construct their own http(s) agent (for example a SocksProxyAgent) and the SDK uses it for all connections; this covers SOCKS and any other proxy scheme without the SDK owning that logic, and drops the socks-proxy-agent runtime dependency. When proxyAgent is set, proxyOptions and tlsParams are ignored (with a warning) because the agent owns connection and TLS setup. - Add `proxyAgent` to server-node LDOptions; forward it through NodePlatform and NodeRequests. - Remove SOCKS scheme handling from NodeRequests and the socks-proxy-agent dependency (kept as a devDependency for the proxy test). - Revert the SOCKS wording added to the shared LDProxyOptions docs. - Rework the proxy test to drive a user-supplied SocksProxyAgent through the hook; update TESTING.md accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@joker23 thanks — that makes sense, and I've reworked the PR along those lines. Rather than the SDK knowing about SOCKS schemes, it now exposes a |
|
Hey @bradbunce thanks for the revision, the PR looks a lot better... I've added some more comments. I think some of comments could be address in later PRs (eg creating example SOCKS implementation). NOTE: I created an internal ticket to track this as |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Reviewed by Cursor Bugbot for commit 4702973. Configure here.
| // certificate-only agent for mTLS). Reporting true is the better default here because | ||
| // proxying is this option's primary motivation, while other connection concerns (such as | ||
| // custom TLS) are handled by tlsParams. | ||
| this._hasProxy = !!proxyOptions || !!proxyAgent; |
There was a problem hiding this comment.
Proxy auth diagnostics ignore agent precedence
Low Severity
When proxyAgent and proxyOptions are both set, the SDK warns and uses only proxyAgent, but usingProxyAuth() still reflects proxyOptions.auth. Init diagnostics can report proxy authentication in use even though that auth is not applied to outbound traffic.
Reviewed by Cursor Bugbot for commit 4702973. Configure here.


Requirements
Related issues
N/A — enables proxy configurations (SOCKS in particular) for environments where outbound access to LaunchDarkly is only available through a proxy the SDK does not build itself.
Describe the solution you've provided
Adds a Node-specific
proxyAgentoption to@launchdarkly/node-server-sdk: anhttp/httpsagent that the SDK uses for all outgoing connections (pollingfetchand the streaming event source). This is an extension point for proxy schemes the SDK does not construct itself — a SOCKS proxy being the motivating example. The application builds its own agent (e.g.new SocksProxyAgent('socks5://host:port')) and hands it to the SDK.This mirrors how the Java server SDK lets developers bring their own
socketFactory, and keeps proxy-scheme knowledge (and correctness) out of the SDK.proxyAgentis added to the server-nodeLDOptionsand wired throughNodePlatformintoNodeRequests.proxyAgentis set, it is used verbatim andproxyOptions/tlsParamsare ignored (with a warning), because the supplied agent owns connection and TLS setup.usingProxy()reportstruefor a custom agent.proxyAgentis omitted, behavior is unchanged: the existinghttps-proxy-agentpath still handlesproxyOptionswithhttp/httpsschemes.socks-proxy-agentis only a devDependency, used by the tests.Describe alternatives you've considered
socks/socks4/socks4a/socks5/socks5hhandling inproxyOptionsbacked by asocks-proxy-agentruntime dependency. Per maintainer feedback this was reworked into the agent hook — it covers SOCKS and any other scheme without the SDK owning that logic, avoids the dependency, and matches the Java SDK's bring-your-own approach.Additional context
End-to-end tests drive a user-supplied
SocksProxyAgentthrough the hook in polling, streaming, and username/password-auth modes, backed by a minimal RFC 1928/1929 SOCKS5 test server (__tests__/socksProxyServer.ts). The fullserver-nodetest suite passes and lint is clean.TESTING.mddocuments how to consume a local build and configureproxyAgent. Relying on CI for the full supported-version matrix (hence the third box left unchecked).Note
Medium Risk
Changes how outbound HTTP/SSE connections are established for all SDK traffic when the option is used; misconfigured agents could break connectivity, though default paths are unchanged.
Overview
Adds a Node-specific
proxyAgentinitialization option so apps can supply their ownhttp/httpsagent for all SDK outbound traffic (polling and streaming), enabling proxy schemes the SDK does not build (e.g. SOCKS viaSocksProxyAgent) without new runtime dependencies.When
proxyAgentis set, it is used as-is;proxyOptionsandtlsParamsare ignored and a warning is logged if both are provided.usingProxy()treats a custom agent as a best-effort “proxy in use” signal. ExistingproxyOptionsbehavior is unchanged whenproxyAgentis omitted.NodeRequestsgains a new constructor parameter (shiftingenableEventCompression); tests cover precedence, warnings, end-to-end client wiring for poll and stream, and agent usage on fetch.Reviewed by Cursor Bugbot for commit 4702973. Bugbot is set up for automated code reviews on this repo. Configure here.