Skip to content

feat: add SOCKS proxy support to server-node SDK#1438

Open
bradbunce wants to merge 2 commits into
launchdarkly:mainfrom
bradbunce:socks-proxy-support
Open

feat: add SOCKS proxy support to server-node SDK#1438
bradbunce wants to merge 2 commits into
launchdarkly:mainfrom
bradbunce:socks-proxy-support

Conversation

@bradbunce

@bradbunce bradbunce commented Jun 9, 2026

Copy link
Copy Markdown

Requirements

  • I have added test coverage for new or changed functionality
  • I have followed the repository's pull request submission guidelines
  • I have validated my changes against all supported platform versions

Related issues

N/A — adds SOCKS proxy support to the Node server SDK for environments where outbound access is only available through a SOCKS proxy.

Describe the solution you've provided

Adds SOCKS proxy support to @launchdarkly/node-server-sdk. Setting proxyOptions.scheme to one of socks, socks4, socks4a, socks5, or socks5h (alongside the existing proxyOptions.host/proxyOptions.port) routes both fetch and event-source (streaming) traffic through a SOCKS proxy, using socks-proxy-agent. A single agent handles both http and https targets.

In NodeRequests, processProxyOptions now branches to a new processSocksProxyOptions when the scheme is a SOCKS scheme; the existing https-proxy-agent path is unchanged for http/https schemes. TLS agent options are forwarded to the SOCKS agent so https targets are still validated.

Credentials from proxyOptions.auth ("username:password", the same format as the HTTP proxy) are applied via a URL object's username/password setters, which percent-encode them; socks-proxy-agent decodes them again. This means a password may safely contain characters such as : (everything after the first colon in auth is treated as the password).

Describe alternatives you've considered

  • Extending the existing https-proxy-agent path — https-proxy-agent only supports HTTP CONNECT proxies, not SOCKS.
  • Hand-encoding credentials into a socks://user:pass@host:port string — rejected in favor of the URL setters, which handle percent-encoding (including : in the password) correctly without manual encodeURIComponent calls.

Additional context

New end-to-end tests cover polling, streaming, and username/password auth (including a colon in the password), backed by a minimal RFC 1928/1929 SOCKS5 test server (__tests__/socksProxyServer.ts). The full server-node test suite passes and lint is clean. Validated locally on Node 20, including against a real Dante SOCKS5 proxy reaching live LaunchDarkly; relying on CI for the full supported-version matrix (hence the third box left unchecked).


Note

Medium Risk
Changes the outbound networking stack for proxied SDK traffic (fetch and SSE), but the change is additive with HTTP proxies untouched and solid e2e coverage.

Overview
Adds SOCKS proxy routing for @launchdarkly/node-server-sdk through the existing proxyOptions config. When scheme is socks, socks4, socks4a, socks5, or socks5h, NodeRequests builds a SocksProxyAgent (new socks-proxy-agent dependency) instead of https-proxy-agent; HTTP/HTTPS proxy behavior is unchanged.

Credentials still use auth as username:password, with only the first : splitting user and password so passwords can contain colons; values are applied via URL username/password setters for correct encoding. The same agent is used for polling fetch and streaming EventSource traffic.

LDProxyOptions JSDoc is updated to document SOCKS schemes. New integration tests use a minimal in-process SOCKS5 server (polling, streaming, and authenticated proxy). TESTING.md documents how to consume a local monorepo build and try SOCKS config before publish.

Reviewed by Cursor Bugbot for commit 597c672. Bugbot is set up for automated code reviews on this repo. Configure here.

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.
@bradbunce bradbunce requested a review from a team as a code owner June 9, 2026 21:36
@bradbunce

Copy link
Copy Markdown
Author

Heads up on CI: the failing checks are all example-app smoke tests (run-example, run-bootstrap-example, run-getting-started-example, run-react-server-example). They fail at the aws-actions/configure-aws-credentials step ("Could not load credentials from any providers") because this PR is from a fork, and fork PRs don't have access to the repo's AWS/OIDC secrets used to fetch the example SDK keys.

All SDK build/test checks relevant to this change pass, including build-test-server-node (20) / (22), build-test-sdk-server, and build-test-common. The example jobs should pass when re-run with the org's credentials.

@joker23

joker23 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

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
Thinking about this more, I think a better approach here is to expose a way for developers to bring their own proxy agent. For example I think our Java server sdk could support SOCKS proxy because developers can specify a sockFactory implementation. In the node server sdk, allowing developers to specify a proxy agent implementation is a close equivalent (and would capture this feature)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 597c672. Configure here.

// A single SOCKS agent works for both http and https targets. Build the proxy address as a URL
// so its username/password setters percent-encode the credentials; socks-proxy-agent decodes
// them again, which means an `auth` password may safely contain characters such as ':'.
const proxyUrl = new URL(`${proxyOptions.scheme}://${proxyOptions.host}:${proxyOptions.port}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SOCKS proxy URL host parsing

Medium Severity

processSocksProxyOptions builds the proxy endpoint with a template string (scheme://host:port) instead of the same formatUrl / URL host handling used for HTTP proxies. IPv6 literals in proxyOptions.host (e.g. ::1) often produce an invalid URL or wrong host/port, and a missing port becomes the literal hostname suffix undefined rather than being omitted.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 597c672. Configure here.

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.

2 participants