@molecule/api-proxy-agent
Utility · proxy-agent · API (Node) · v1.1.1 · Apache-2.0
CONNECT-capable HTTP(S) proxy agent built from the standard proxy environment (HTTPS_PROXY / HTTP_PROXY / NO_PROXY), for vendor SDKs that build their own HTTP agent and ignore it.
npm install @molecule/api-proxy-agentHow it works
@molecule/api-proxy-agent is a utility package for the API (Node) side (proxy-agent).
import { getProxyAgent, getProxyAgents } from '@molecule/api-proxy-agent'
// Stripe: `httpAgent` is used for every request the client makes.
const stripe = new Stripe(key, { httpAgent: getProxyAgent('https://api.stripe.com') })
// AWS SDK v3 (any client): `requestHandler` takes NodeHttpHandler options,
// so no extra `@smithy/*` dependency is needed.
const proxy = getProxyAgents(`https://email.${region}.amazonaws.com`)
const ses = new SESv2Client({ region, ...(proxy ? { requestHandler: proxy } : {}) })Reference
A CONNECT-capable proxy agent built from the standard proxy environment, for the vendor SDKs that ignore it.
Most HTTP clients already honour HTTPS_PROXY/HTTP_PROXY/NO_PROXY: Node's
global fetch does under NODE_USE_ENV_PROXY=1, and so do axios-based SDKs.
A handful do not — they build their own http.Agent or undici pool and dial
the vendor directly. On a workstation that direct connection succeeds, so the
difference is invisible; in an environment whose ONLY egress path is a proxy
(a molecule.dev sandbox, a deployed molecule.dev app, a locked-down VPC) the
same call fails with a bare connection error naming nothing.
Each of those SDKs does accept an agent — it just will not build one for you.
getProxyAgent(url) builds it, and returns undefined when no proxy applies
so the SDK keeps its own default and an app running outside a proxied
environment is completely unaffected.
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
import { getProxyAgent, getProxyAgents } from '@molecule/api-proxy-agent'
// Stripe: `httpAgent` is used for every request the client makes.
const stripe = new Stripe(key, { httpAgent: getProxyAgent('https://api.stripe.com') })
// AWS SDK v3 (any client): `requestHandler` takes NodeHttpHandler options,
// so no extra `@smithy/*` dependency is needed.
const proxy = getProxyAgents(`https://email.${region}.amazonaws.com`)
const ses = new SESv2Client({ region, ...(proxy ? { requestHandler: proxy } : {}) })
Type
utility
Installation
npm install @molecule/api-proxy-agent http-proxy-agent https-proxy-agent proxy-from-env
npm install -D @types/proxy-from-env
API
Interfaces
ProxyAgentOptions
Options for getProxyAgent / getProxyUrl / shouldProxy.
interface ProxyAgentOptions {
/**
* Keep the tunnelled socket alive between requests. Defaults to `true`,
* matching what every SDK in this class does with its own default agent —
* a proxy agent that closes the socket per request would silently make a
* chatty SDK (S3 multipart, SQS long-poll) far slower than it was before.
*/
keepAlive?: boolean
}
Types
ProxyAgent
An agent this package can hand to a vendor SDK. http: targets get an
http.Agent, https: targets an https.Agent — both tunnel through the
configured proxy.
type ProxyAgent = HttpAgent | HttpsAgent
Functions
getProxyUrl(targetUrl)
Returns the proxy URL that should serve targetUrl according to the standard
proxy environment (HTTPS_PROXY / HTTP_PROXY / ALL_PROXY, either case),
or undefined when the target is not proxied — either because no proxy is
configured, or because NO_PROXY exempts it.
function getProxyUrl(targetUrl: string): string | undefined
targetUrl— The absolute URL the SDK is about to call.
Returns: The proxy URL, or undefined to connect directly.
shouldProxy(targetUrl)
Whether targetUrl should be sent through a proxy.
function shouldProxy(targetUrl: string): boolean
targetUrl— The absolute URL the SDK is about to call.
Returns: true when a proxy is configured for this target.
getProxyAgent(targetUrl, options)
Returns an agent that tunnels targetUrl through the configured proxy via
CONNECT, or undefined when this target is not proxied.
undefined is the whole contract: a call site passes the result straight into
its SDK's own agent option, so with no proxy configured the SDK keeps its own
default agent and behaves exactly as it did before. Nothing is monkey-patched
and nothing changes for an app running outside a proxied environment.
function getProxyAgent(targetUrl: string, options?: ProxyAgentOptions): ProxyAgent | undefined
targetUrl— The absolute URL the SDK is about to call. It decides both which env var applies (https_proxyvshttp_proxy) and whetherNO_PROXYexempts the host, so pass the real vendor endpoint — not a placeholder.options— SeeProxyAgentOptions.
Returns: An http.Agent/https.Agent that tunnels through the proxy, or undefined when the target is not proxied.
getProxyAgents(targetUrl, options)
Returns { httpAgent } or { httpsAgent } — whichever matches targetUrl's
protocol — or undefined when the target is not proxied.
This is the shape AWS SDK v3's requestHandler accepts directly (it takes
NodeHttpHandler OPTIONS, so no @smithy/node-http-handler dependency is
needed), and it is also what got and node-fetch take. Spread it, so that
an unproxied environment adds no key at all:
const proxy = getProxyAgents(endpoint)
new S3Client({ region, ...(proxy ? { requestHandler: proxy } : {}) })
function getProxyAgents(
targetUrl: string,
options?: ProxyAgentOptions,
): { httpAgent?: ProxyAgent; httpsAgent?: ProxyAgent } | undefined
targetUrl— The absolute URL the SDK is about to call.options— SeeProxyAgentOptions.
Returns: The agent pair, or undefined when the target is not proxied.
resetProxyAgents()
Drops every memoized agent, destroying its sockets.
Only useful when the proxy environment changes inside a live process — a test
that mutates process.env, or a secrets bond that resolves HTTPS_PROXY
after the first call. Ordinary application code never needs it.
function resetProxyAgents(): void
Injection Notes
Runtime Dependencies
-
http-proxy-agent -
https-proxy-agent -
proxy-from-env -
Pass the REAL endpoint, not a placeholder. The target URL decides which variable applies (
https_proxyvshttp_proxy) and whetherNO_PROXYexempts the host.getProxyAgent('https://example.com')standing in for an S3 call would consult the wrongNO_PROXYentry. -
Spread the result, never pass it unconditionally. Several SDKs treat a present-but-
undefinedagent option as "use no agent" rather than "use the default"....(agent ? { httpAgent: agent } : {})is the shape that is a true no-op when nothing is proxied. -
Agents are memoized per proxy URL, because an agent owns a connection pool — building a fresh one per call opens a new tunnel every request. Call it inside your lazy client getter and keep the client, not the agent.
-
This cannot rescue an SDK that vendors its own proxy handling. If a library bundles a copy of its HTTP client and offers no agent option, there is no hook to pass this into; the fix has to be upstream or in the proxy.
-
HTTP(S) only. A raw-TCP client — Postgres, MySQL, Redis, Mongo, AMQP, SMTP — cannot be tunnelled by an HTTP proxy at all. Those need a network path to the host, not an agent.
-
Built on
https-proxy-agent/http-proxy-agent(the CONNECT tunnel) andproxy-from-env(the env +NO_PROXYsemantics, the same resolver axios uses) rather than a hand-rolled parser:NO_PROXYhas enough real edge cases — leading dots,*, per-entry ports, IPv6 brackets — that a bespoke one would be wrong in exactly the situations it matters.