A PAC file proxy http.Agent implementation for HTTP and HTTPS connections
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
PAC 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