Modes
Proxyline models two safety postures. The mode option selects one explicitly — there is no implicit fallback between them.
#Managed
Managed mode treats proxy routing as a security policy.
proxyUrlis required. Omitting it throwsProxylineErrorwith codeMANAGED_PROXY_URL_REQUIRED.- Only
http://andhttps://proxy endpoints are accepted. Other schemes throwUNSUPPORTED_PROXY_PROTOCOL. - The managed proxy is forced for HTTP(S) and WS(S) requests on the patched surfaces.
bypassPolicy,registerBypass(), andwithBypass()are the managed-mode direct-routing escape hatches. They match{ surface, url }and intentionally send matching requests direct.registerBypass()is process-wide until unregistered;withBypass()is limited to the callback's async context.- Caller-supplied
http.Agentorhttps.Agentvalues are replaced per request. TLS-relevant agent options (ca,cert,key,ciphers,minVersion,maxVersion,rejectUnauthorized, etc.) are copied onto the proxy request so destination TLS identity is preserved. See Surfaces — TLS identity preservation for the full list. - The undici global dispatcher is replaced with Proxyline's managed dispatcher, backed by
undici.ProxyAgentinstances pointed atproxyUrl. - Environment variables (
HTTP_PROXY,HTTPS_PROXY,NO_PROXY, ...) are ignored. explain()returnskind: "proxied"withreason: "managed-proxy-active"for supported URL schemes. Bypassed URLs returnkind: "direct"withreason: "managed-proxy-bypass-policy". Unsupported schemes returnkind: "direct"withreason: "managed-proxy-unsupported-url-scheme"because Proxyline has no safe proxy mapping for them.
Use managed mode when "go direct" must never be silent. If your network policy demands traffic egress through a specific gateway, this is the posture you want.
const proxy = installGlobalProxy({
mode: "managed",
proxyUrl: "https://proxy.corp.example:8443",
proxyTls: { caFile: "/etc/proxy-ca.pem" },
bypassPolicy: ({ url }) => new URL(url).hostname === "127.0.0.1",
});
#Ambient
Ambient mode mirrors the conventional "respect the environment" behavior used by most CLI tooling.
proxyUrlis ignored if supplied. Configuration comes fromHTTP_PROXY,HTTPS_PROXY,ALL_PROXY, andNO_PROXY(and their lowercase forms).- The runtime only installs patches when at least one of
HTTP_PROXY,HTTPS_PROXY, orALL_PROXYresolves to a supportedhttp://orhttps://proxy endpoint.proxy.activeisfalseotherwise and the handle behaves as a passive observer. - Per-request proxy resolution honors protocol-specific variables, falls back to
ALL_PROXY, and appliesNO_PROXYmatching (suffix, wildcard, exact, IPv6). - Bare endpoints (no scheme) default to
http://— e.g.HTTPS_PROXY=proxy.corp:8080becomeshttp://proxy.corp:8080. - The undici global dispatcher becomes Proxyline's ambient dispatcher so
fetchsees the same routing rules. explain()returns one of:kind: "proxied",reason: "ambient-proxy-active"— a proxy applies.kind: "direct",reason: "no-proxy-match"—NO_PROXYexempted the host.kind: "direct",reason: "ambient-proxy-not-configured"— no supported proxy variables are set, the configured proxy scheme is unsupported, or the URL scheme is unsupported.
Use ambient mode for tooling and CLIs that need best-effort compatibility with whatever the operator has configured.
const proxy = installGlobalProxy({ mode: "ambient" });
if (!proxy.active) {
console.warn("no HTTP_PROXY/HTTPS_PROXY/ALL_PROXY set — direct egress");
}
#Comparison
| Behavior | managed | ambient |
|---|---|---|
Requires proxyUrl | yes | no (ignored if passed) |
| Reads env variables | no | yes |
Honors NO_PROXY | no | yes |
Supports bypassPolicy | yes | no |
| Forces traffic through proxy | yes | only when env says so |
| Replaces caller-supplied agents | yes | yes (when active) |
| Installs undici dispatcher | ProxyAgent | Proxyline ambient dispatcher |
explain() direct reason | managed-proxy-bypass-policy or managed-proxy-unsupported-url-scheme | no-proxy-match or ambient-proxy-not-configured |
| Setup failure mode | throws | inactive but installed |
#Why a strict managed mode
If you mix environment-based configuration with a security policy you get drift: a missing variable, a forgotten NO_PROXY entry, or a transient unset turns "always through the proxy" into "sometimes direct." Managed mode refuses to start without the URL and refuses to honor environment overrides, so the policy is encoded in code, not in shell state.