Skip to content

refactor(cli): replace ancient tunnel with dedicated proxy agents#1157

Open
sorccu wants to merge 3 commits into
mainfrom
simo/sim-138-cli-replace-7-year-told-tunnel-package-with-proxy-agent
Open

refactor(cli): replace ancient tunnel with dedicated proxy agents#1157
sorccu wants to merge 3 commits into
mainfrom
simo/sim-138-cli-replace-7-year-told-tunnel-package-with-proxy-agent

Conversation

@sorccu

@sorccu sorccu commented Oct 6, 2025

Copy link
Copy Markdown
Member

Replaces the ~7-year-old tunnel package with the maintained http-proxy-agent, https-proxy-agent, and socks-proxy-agent, selecting the right agent per target URL via proxy-from-env's getProxyForUrl (which honors HTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXY). tunnel's behavior on current Node is uncertain and it complicated MITM/proxy debugging.

Resolves SIM-138. This supersedes the original attempt on this branch (rebased onto the pnpm monorepo).

What changed

  • Remove tunnel + @types/tunnel; add http-proxy-agent, https-proxy-agent, socks-proxy-agent.
  • Centralize proxy handling in services/proxy.ts:
    • createProxyAgent(targetUrl) — returns the agent for the target (HTTPS/HTTP/SOCKS) or undefined for a direct connection. ws:/wss: are mapped to their HTTP equivalents for proxy selection.
    • assignProxy(targetUrl, config) — installs the agent and sets proxy: false.
  • Route every proxy path through the helper: rest/api.ts, auth/index.ts, helpers/result-assets.ts, services/socket-client.ts (via wsOptions.agent), plus two axios.get calls that previously ignored proxy settings entirely (commands/baseCommand.ts npm version check, rest/assets.ts V2 asset download).
  • Add services/proxy.spec.ts covering agent selection (http/https/socks/wss/NO_PROXY/direct) and a behavioral test that a portless target host is forwarded through a local proxy without the proxy port appended.

Why the original was blocked — and the fix

The first version of this change dropped the old helper but didn't set proxy: false, so axios re-read the proxy env vars itself and appended the proxy's port to portless targets (https://api.checklyhq.com:8080). Centralizing proxy: false in assignProxy makes the invariant impossible to forget at a call site.

Why dedicated agents instead of proxy-agent

An interim version used the proxy-agent meta-package. It pulls ~5 MB (≈3 MB of which is a QuickJS WASM blob) solely to evaluate PAC files — and that PAC support cannot honor system/WPAD proxy configuration anyway (it only triggers on a non-standard pac+... env var). The three dedicated agents cover every proxy setup the CLI actually uses, including SOCKS, for ~180 KB.

Better proxy errors

When a proxy is configured but unreachable, the connection (made to the proxy first) failed with ECONNREFUSED and the CLI showed a generic "check that the internet connection is working" message. It now throws a ProxyConnectionError naming the proxy (credentials stripped), e.g. "Could not connect to the proxy at http://localhost:1234. Check that the proxy is running and that the http_proxy/https_proxy/all_proxy environment variables point to the correct address." Requests made without a proxy keep the generic message.

Affected Components

  • CLI

Notes for the Reviewer

proxy: false in assignProxy is load-bearing — see the regression test for the exact behavior it guards.

@sorccu sorccu force-pushed the simo/sim-138-cli-replace-7-year-told-tunnel-package-with-proxy-agent branch from 65fa143 to 70d8793 Compare October 6, 2025 23:23
@sorccu sorccu force-pushed the simo/sim-138-cli-replace-7-year-told-tunnel-package-with-proxy-agent branch from 70d8793 to 16fed95 Compare February 12, 2026 22:52
@sorccu sorccu force-pushed the simo/sim-138-cli-replace-7-year-told-tunnel-package-with-proxy-agent branch from 16fed95 to 7c79611 Compare June 29, 2026 08:30
@sorccu sorccu changed the title chore: replace ancient tunnel + proxy-from-env with proxy-agent refactor(cli): replace ancient tunnel with proxy-agent Jun 29, 2026
@sorccu sorccu force-pushed the simo/sim-138-cli-replace-7-year-told-tunnel-package-with-proxy-agent branch from 7c79611 to 834c22b Compare June 29, 2026 09:19
sorccu and others added 2 commits June 29, 2026 19:46
…M-138]

Drop the ~7-year-old `tunnel` package in favour of the maintained
`http-proxy-agent`, `https-proxy-agent`, and `socks-proxy-agent`, selecting
the right agent per target URL via `getProxyForUrl` (which honors
HTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXY).

Proxy handling is centralized in services/proxy.ts: `createProxyAgent`
returns the agent for a target URL (or undefined for a direct connection),
and `assignProxy` installs it on an axios config and sets `proxy: false`.
Setting `proxy: false` is mandatory — otherwise axios re-reads the proxy env
vars itself and appends the proxy's port to portless target URLs
(e.g. https://api.checklyhq.com -> :8080).

All proxy paths now go through the helper, including two axios.get calls
that previously ignored proxy settings entirely (the npm version check in
baseCommand and the V2 asset download in rest/assets). The WebSocket client
uses createProxyAgent directly via wsOptions.

These focused agents add ~180 KB versus the ~5 MB `proxy-agent` meta-package
(whose 3 MB QuickJS WASM only powers PAC evaluation, which cannot honor
system/WPAD proxy configuration anyway). SOCKS proxies remain supported.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ks4mnGCV1MAK69MMzojmcx
…t [SIM-138]

Add proxy.spec.ts covering createProxyAgent selection (http/https/socks/wss,
NO_PROXY, and direct when unset), that assignProxy always sets `proxy: false`
and shares one agent across both slots, and a behavioral test that a portless
target host is forwarded through a local proxy without the proxy port appended.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ks4mnGCV1MAK69MMzojmcx
@sorccu sorccu force-pushed the simo/sim-138-cli-replace-7-year-told-tunnel-package-with-proxy-agent branch from 834c22b to 188707c Compare June 29, 2026 10:47
@sorccu sorccu changed the title refactor(cli): replace ancient tunnel with proxy-agent refactor(cli): replace ancient tunnel with dedicated proxy agents Jun 29, 2026
@checkly checkly deleted a comment from github-actions Bot Jun 29, 2026
…ble [SIM-138]

When a proxy is set but down, the connection (made to the proxy first) fails
with ECONNREFUSED and the user previously saw the generic "check that the
internet connection is working" message, which points at the wrong thing.

handleErrorResponse now throws a ProxyConnectionError that names the proxy
(credentials stripped) when a proxy applies to the request and the failure is
a connection-level error (ECONNREFUSED/ETIMEDOUT/EHOSTUNREACH/ENETUNREACH/
ENOTFOUND/EAI_AGAIN), found by walking the error's cause chain and any
AggregateError. Requests without a proxy keep the generic message.

A getProxyUrl helper is extracted in services/proxy.ts to resolve the proxy
for a target URL using the same env-var rules as agent selection.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ks4mnGCV1MAK69MMzojmcx
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.

1 participant