A PAC file proxy http.Agent implementation for HTTP and HTTPS connections
npx @tessl/cli install tessl/npm-pac-proxy-agent@7.2.0PAC Proxy Agent provides an HTTP Agent implementation that retrieves and uses PAC (Proxy Auto-Configuration) files to determine the appropriate proxy server for HTTP and HTTPS connections. It integrates seamlessly with Node.js built-in HTTP and HTTPS modules, automatically resolving whether to use HTTP, HTTPS, or SOCKS proxies, or establish direct connections based on PAC file rules.
npm install pac-proxy-agentimport { PacProxyAgent, type PacProxyAgentOptions } from "pac-proxy-agent";For CommonJS:
const { PacProxyAgent } = require("pac-proxy-agent");import * as http from 'http';
import { PacProxyAgent } from 'pac-proxy-agent';
// Create agent with PAC file URL
const agent = new PacProxyAgent('pac+https://example.com/proxy.pac');
// Use with http.get
http.get('http://nodejs.org/api/', { agent }, (res) => {
console.log('Response headers:', res.headers);
res.pipe(process.stdout);
});
// Use with https requests
import * as https from 'https';
const httpsAgent = new PacProxyAgent('pac+https://example.com/proxy.pac');
https.get('https://api.example.com/data', { agent: httpsAgent }, (res) => {
// Handle response
});PAC Proxy Agent is built around several key components:
The main proxy agent class that handles PAC file resolution and proxy connection management.
/**
* PAC Proxy Agent implementation that loads PAC files and resolves proxy settings
* Supports various PAC file protocols: data, file, ftp, http, https
*/
class PacProxyAgent<Uri extends string> extends Agent {
/** Supported PAC protocols */
static readonly protocols: Array<'pac+data' | 'pac+file' | 'pac+ftp' | 'pac+http' | 'pac+https'>;
/** PAC file URI (with pac+ prefix stripped) */
uri: URL;
/** Configuration options */
opts: PacProxyAgentOptions<Uri>;
/** Cached PAC file stream (undefined if not loaded) */
cache?: Readable;
/** Cached PAC resolver function (undefined if not loaded) */
resolver?: FindProxyForURL;
/** SHA1 hash of current PAC file content for change detection */
resolverHash: string;
/** Promise for resolver loading (undefined when not loading) */
resolverPromise?: Promise<FindProxyForURL>;
/**
* Creates a new PAC Proxy Agent
* @param uri - PAC file URI with protocol prefix (pac+http://..., pac+file://..., etc.)
* @param opts - Configuration options
*/
constructor(uri: Uri | URL, opts?: PacProxyAgentOptions<Uri>);
/**
* Loads the PAC proxy file and returns a resolver function
* Caches the resolver and reuses it if the PAC file content hasn't changed
* @returns Promise resolving to FindProxyForURL function
*/
getResolver(): Promise<FindProxyForURL>;
/**
* Establishes connection through appropriate proxy based on PAC resolution
* Called automatically by Node.js HTTP client when making requests
* @param req - HTTP client request
* @param opts - Connection options including host, port, secureEndpoint
* @returns Promise resolving to Agent or Socket for the connection
*/
connect(req: http.ClientRequest, opts: AgentConnectOpts): Promise<http.Agent | net.Socket>;
}Comprehensive options interface combining settings from multiple proxy agent types.
/**
* Configuration options for PacProxyAgent
* Combines options from http.Agent, PAC resolver, and various proxy agents
*/
interface PacProxyAgentOptions<T> extends
http.AgentOptions,
PacResolverOptions,
GetUriOptions<Protocol<T>>,
HttpProxyAgentOptions<''>,
HttpsProxyAgentOptions<''>,
SocksProxyAgentOptions {
/**
* Whether to fall back to direct connection if all proxies fail
* When true, adds 'DIRECT' to the end of proxy list
* @default false
*/
fallbackToDirect?: boolean;
}The agent supports loading PAC files from multiple sources with automatic protocol detection.
Supported Protocols:
pac+data: - Embedded data URI containing PAC file contentpac+file: - Local file system path to PAC filepac+ftp: - FTP server hosting PAC filepac+http: - HTTP endpoint serving PAC filepac+https: - HTTPS endpoint serving PAC fileUsage Examples:
// Data URI with embedded PAC file
const dataAgent = new PacProxyAgent('pac+data:,function FindProxyForURL(){return "PROXY proxy.example.com:8080";}');
// Local PAC file
const fileAgent = new PacProxyAgent('pac+file:///etc/proxy.pac');
// Remote PAC file over HTTPS
const httpsAgent = new PacProxyAgent('pac+https://config.company.com/proxy.pac');
// With custom options
const customAgent = new PacProxyAgent('pac+https://config.company.com/proxy.pac', {
fallbackToDirect: true,
timeout: 5000,
rejectUnauthorized: false // for self-signed certificates
});Based on PAC file resolution, the agent automatically selects the appropriate proxy implementation.
Supported Proxy Types:
DIRECT - Direct connection to destination (no proxy)PROXY / HTTP - HTTP proxy connectionHTTPS - HTTPS proxy connectionSOCKS / SOCKS5 - SOCKS5 proxy connectionSOCKS4 - SOCKS4 proxy connectionProxy Resolution Flow:
// PAC file example that returns multiple proxy options
function FindProxyForURL(url, host) {
if (host === "internal.company.com") {
return "DIRECT";
}
return "PROXY proxy1.company.com:8080; PROXY proxy2.company.com:8080; DIRECT";
}The agent will try each proxy in sequence until one succeeds or all fail.
The agent emits events on the HTTP request object to provide visibility into proxy selection.
/**
* Proxy events emitted on the HTTP request object
*/
interface ProxyEvent {
/** The proxy string being attempted (e.g., "PROXY proxy.example.com:8080") */
proxy: string;
/** The socket connection (present on successful connection) */
socket?: net.Socket;
/** Error that occurred (present on connection failure) */
error?: Error;
}Event Usage Example:
import { PacProxyAgent } from 'pac-proxy-agent';
import * as http from 'http';
const agent = new PacProxyAgent('pac+https://config.company.com/proxy.pac');
const req = http.get('http://api.example.com/data', { agent }, (res) => {
console.log('Request succeeded');
});
// Listen for proxy selection events
req.on('proxy', ({ proxy, socket, error }) => {
if (error) {
console.log(`Proxy ${proxy} failed:`, error.message);
} else {
console.log(`Using proxy: ${proxy}`);
}
});The agent handles various error scenarios gracefully with built-in fallback mechanisms.
Common Error Scenarios:
Error Handling Example:
import { PacProxyAgent } from 'pac-proxy-agent';
import * as http from 'http';
const agent = new PacProxyAgent('pac+https://config.company.com/proxy.pac', {
fallbackToDirect: true // Enable direct connection fallback
});
try {
const req = http.get('http://api.example.com/data', { agent }, (res) => {
console.log('Success:', res.statusCode);
});
req.on('error', (error) => {
console.error('Request failed:', error.message);
});
req.on('proxy', ({ proxy, error }) => {
if (error) {
console.log(`Proxy ${proxy} failed, trying next...`);
}
});
} catch (error) {
console.error('Agent setup failed:', error.message);
}/**
* Readable stream from Node.js stream module
* Used for PAC file content caching
*/
interface Readable {
// Node.js Readable stream interface (from 'stream' module)
}
/**
* FindProxyForURL function signature from PAC file
* Standard PAC function that determines proxy configuration for a given URL
*/
type FindProxyForURL = (url: string, host: string) => string | Promise<string>;
/**
* Agent connection options passed to connect method
* From 'agent-base' package - contains connection details like host, port, and security settings
*/
interface AgentConnectOpts {
/** Target hostname */
host: string;
/** Target port number */
port: number;
/** Whether this is an HTTPS connection */
secureEndpoint: boolean;
/** Additional connection options */
[key: string]: any;
}
/**
* Protocol extraction utility type
* Extracts the protocol portion from PAC URI strings
*/
type Protocol<T> = T extends `pac+${infer P}:${infer _}`
? P
: T extends `${infer P}:${infer _}`
? P
: never;The package integrates with several proxy agent libraries. While these types are not directly exported, they're used in the options interface:
PacResolverOptions - from 'pac-resolver' packageGetUriOptions - from 'get-uri' packageHttpProxyAgentOptions - from 'http-proxy-agent' packageHttpsProxyAgentOptions - from 'https-proxy-agent' packageSocksProxyAgentOptions - from 'socks-proxy-agent' package