An HTTP/1.1 client, written from scratch for Node.js
—
Dispatcher classes for managing HTTP connections at different scales, from single connections to multi-origin load balancing.
Basic HTTP/1.1 client for single TCP/TLS connections. Ideal for simple use cases requiring connection to a single origin.
/**
* HTTP client for single TCP/TLS connections
*/
class Client extends Dispatcher {
constructor(url: string | URL, options?: Client.Options);
// Inherited from Dispatcher
request(options: RequestOptions): Promise<ResponseData>;
stream(options: RequestOptions, factory: StreamFactory): Promise<StreamData>;
pipeline(options: PipelineOptions, handler: PipelineHandler): Duplex;
connect(options: ConnectOptions): Promise<ConnectData>;
upgrade(options: UpgradeOptions): Promise<UpgradeData>;
close(): Promise<void>;
destroy(err?: Error): Promise<void>;
}
interface Client.Options {
bodyTimeout?: number;
headersTimeout?: number;
keepAliveMaxTimeout?: number;
keepAliveTimeout?: number;
keepAliveTimeoutThreshold?: number;
maxHeaderSize?: number;
maxResponseSize?: number;
pipelining?: number;
connect?: ConnectOptions | ConnectFunction;
strictContentLength?: boolean;
}Usage Examples:
import { Client } from 'undici';
// Basic client setup
const client = new Client('https://api.example.com');
// Make requests
const { statusCode, body } = await client.request({
path: '/users',
method: 'GET'
});
const users = await body.json();
// Configure client options
const configuredClient = new Client('https://api.example.com', {
keepAliveTimeout: 10000,
pipelining: 1,
bodyTimeout: 5000
});
// Always close when done
await client.close();Connection pool for managing multiple clients to the same origin. Provides automatic connection pooling and lifecycle management.
/**
* Connection pool for single origin with multiple connections
*/
class Pool extends Dispatcher {
constructor(url: string | URL, options?: Pool.Options);
// Inherited from Dispatcher
request(options: RequestOptions): Promise<ResponseData>;
stream(options: RequestOptions, factory: StreamFactory): Promise<StreamData>;
pipeline(options: PipelineOptions, handler: PipelineHandler): Duplex;
connect(options: ConnectOptions): Promise<ConnectData>;
upgrade(options: UpgradeOptions): Promise<UpgradeData>;
close(): Promise<void>;
destroy(err?: Error): Promise<void>;
}
interface Pool.Options extends Client.Options {
connections?: number;
factory?: (origin: URL, opts: object) => Dispatcher;
}Usage Examples:
import { Pool } from 'undici';
// Pool with multiple connections
const pool = new Pool('https://api.example.com', {
connections: 10,
pipelining: 1
});
// Make concurrent requests efficiently
const promises = Array.from({ length: 100 }, (_, i) =>
pool.request({ path: `/users/${i}` })
);
const responses = await Promise.all(promises);
// Pool automatically manages connections
await pool.close();Load balancer across multiple upstream servers. Distributes requests across multiple origins with automatic failover.
/**
* Load balancer across multiple upstream servers
*/
class BalancedPool extends Dispatcher {
constructor(upstreams: string[] | URL[], options?: BalancedPool.Options);
addUpstream(upstream: string | URL): BalancedPool;
removeUpstream(upstream: string | URL): BalancedPool;
upstreams: Array<string>;
// Inherited from Dispatcher
request(options: RequestOptions): Promise<ResponseData>;
stream(options: RequestOptions, factory: StreamFactory): Promise<StreamData>;
pipeline(options: PipelineOptions, handler: PipelineHandler): Duplex;
connect(options: ConnectOptions): Promise<ConnectData>;
upgrade(options: UpgradeOptions): Promise<UpgradeData>;
close(): Promise<void>;
destroy(err?: Error): Promise<void>;
}
interface BalancedPool.Options extends Pool.Options {
factory?: (origin: URL, opts: object) => Dispatcher;
}Usage Examples:
import { BalancedPool } from 'undici';
// Create load balancer with multiple upstreams
const balancer = new BalancedPool([
'https://api1.example.com',
'https://api2.example.com',
'https://api3.example.com'
]);
// Requests are automatically distributed
const { body } = await balancer.request({ path: '/users' });
const users = await body.json();
// Add/remove upstreams dynamically
balancer.addUpstream('https://api4.example.com');
balancer.removeUpstream('https://api1.example.com');
await balancer.close();Agent for managing multiple pools across different origins. Provides automatic origin-based routing and connection pooling.
/**
* Agent for managing multiple pools across different origins
*/
class Agent extends Dispatcher {
constructor(options?: Agent.Options);
// Inherited from Dispatcher
request(options: RequestOptions): Promise<ResponseData>;
stream(options: RequestOptions, factory: StreamFactory): Promise<StreamData>;
pipeline(options: PipelineOptions, handler: PipelineHandler): Duplex;
connect(options: ConnectOptions): Promise<ConnectData>;
upgrade(options: UpgradeOptions): Promise<UpgradeData>;
close(): Promise<void>;
destroy(err?: Error): Promise<void>;
}
interface Agent.Options {
factory?: (origin: URL, opts: object) => Dispatcher;
maxRedirections?: number;
interceptors?: {
Agent?: readonly DispatcherComposeInterceptor[];
Client?: readonly DispatcherComposeInterceptor[];
};
}Usage Examples:
import { Agent } from 'undici';
// Create agent for multiple origins
const agent = new Agent({
factory: (origin, opts) => {
return new Pool(origin, { ...opts, connections: 5 });
}
});
// Make requests to different origins
const [users, posts] = await Promise.all([
agent.request({
origin: 'https://users-api.example.com',
path: '/users'
}),
agent.request({
origin: 'https://posts-api.example.com',
path: '/posts'
})
]);
// Agent automatically manages pools per origin
await agent.close();HTTP proxy agent for routing requests through proxy servers.
/**
* HTTP proxy agent for routing requests through proxies
*/
class ProxyAgent extends Dispatcher {
constructor(options: ProxyAgent.Options | string);
// Inherited from Dispatcher
request(options: RequestOptions): Promise<ResponseData>;
stream(options: RequestOptions, factory: StreamFactory): Promise<StreamData>;
pipeline(options: PipelineOptions, handler: PipelineHandler): Duplex;
connect(options: ConnectOptions): Promise<ConnectData>;
upgrade(options: UpgradeOptions): Promise<UpgradeData>;
close(): Promise<void>;
destroy(err?: Error): Promise<void>;
}
interface ProxyAgent.Options {
uri: string;
token?: string;
auth?: string;
factory?: (origin: URL, opts: object) => Dispatcher;
requestTls?: BuildOptions;
proxyTls?: BuildOptions;
interceptors?: {
ProxyAgent?: readonly DispatcherComposeInterceptor[];
};
}Usage Examples:
import { ProxyAgent } from 'undici';
// HTTP proxy
const proxyAgent = new ProxyAgent('http://proxy.example.com:8080');
// HTTPS proxy with authentication
const authProxyAgent = new ProxyAgent({
uri: 'https://proxy.example.com:8080',
token: 'Bearer token123',
auth: 'user:password'
});
// Use proxy for requests
const { body } = await proxyAgent.request({
origin: 'https://api.example.com',
path: '/data'
});
await proxyAgent.close();Environment-based HTTP proxy agent that automatically uses HTTP_PROXY and HTTPS_PROXY environment variables.
/**
* Environment-based HTTP proxy agent using env vars
*/
class EnvHttpProxyAgent extends Dispatcher {
constructor(options?: EnvHttpProxyAgent.Options);
// Inherited from Dispatcher
request(options: RequestOptions): Promise<ResponseData>;
stream(options: RequestOptions, factory: StreamFactory): Promise<StreamData>;
pipeline(options: PipelineOptions, handler: PipelineHandler): Duplex;
connect(options: ConnectOptions): Promise<ConnectData>;
upgrade(options: UpgradeOptions): Promise<UpgradeData>;
close(): Promise<void>;
destroy(err?: Error): Promise<void>;
}
interface EnvHttpProxyAgent.Options {
factory?: (origin: URL, opts: object) => Dispatcher;
interceptors?: {
EnvHttpProxyAgent?: readonly DispatcherComposeInterceptor[];
};
}Usage Examples:
import { EnvHttpProxyAgent } from 'undici';
// Set environment variables
process.env.HTTP_PROXY = 'http://proxy.example.com:8080';
process.env.HTTPS_PROXY = 'https://secure-proxy.example.com:8080';
process.env.NO_PROXY = 'localhost,127.0.0.1,.internal';
// Agent automatically uses environment settings
const envAgent = new EnvHttpProxyAgent();
const { body } = await envAgent.request({
origin: 'https://api.example.com',
path: '/data'
});
await envAgent.close();Agent with automatic retry capabilities for handling transient failures.
/**
* Agent with automatic retry capabilities
*/
class RetryAgent extends Dispatcher {
constructor(dispatcher: Dispatcher, options?: RetryAgent.Options);
// Inherited from Dispatcher
request(options: RequestOptions): Promise<ResponseData>;
stream(options: RequestOptions, factory: StreamFactory): Promise<StreamData>;
pipeline(options: PipelineOptions, handler: PipelineHandler): Duplex;
connect(options: ConnectOptions): Promise<ConnectData>;
upgrade(options: UpgradeOptions): Promise<UpgradeData>;
close(): Promise<void>;
destroy(err?: Error): Promise<void>;
}
interface RetryAgent.Options {
retry?: RetryOptions;
interceptors?: {
RetryAgent?: readonly DispatcherComposeInterceptor[];
};
}
interface RetryOptions {
retry?: (err: Error, context: RetryContext) => number | null;
maxRetries?: number;
maxTimeout?: number;
minTimeout?: number;
timeoutFactor?: number;
retryAfter?: boolean;
methods?: string[];
statusCodes?: number[];
errorCodes?: string[];
}Usage Examples:
import { RetryAgent, Pool } from 'undici';
// Create retry agent with custom retry logic
const retryAgent = new RetryAgent(
new Pool('https://api.example.com'),
{
retry: (err, { attempt, maxRetries }) => {
if (attempt >= maxRetries) return null;
// Exponential backoff
return Math.min(1000 * (2 ** attempt), 10000);
},
maxRetries: 3,
methods: ['GET', 'HEAD', 'OPTIONS'],
statusCodes: [408, 413, 429, 500, 502, 503, 504]
}
);
// Requests automatically retry on failure
const { body } = await retryAgent.request({ path: '/unreliable-endpoint' });
await retryAgent.close();HTTP/2 cleartext client for HTTP/2 connections without TLS.
/**
* HTTP/2 cleartext client
*/
class H2CClient extends Dispatcher {
constructor(url: string | URL, options?: H2CClient.Options);
// Inherited from Dispatcher
request(options: RequestOptions): Promise<ResponseData>;
stream(options: RequestOptions, factory: StreamFactory): Promise<StreamData>;
pipeline(options: PipelineOptions, handler: PipelineHandler): Duplex;
connect(options: ConnectOptions): Promise<ConnectData>;
upgrade(options: UpgradeOptions): Promise<UpgradeData>;
close(): Promise<void>;
destroy(err?: Error): Promise<void>;
}
interface H2CClient.Options {
maxConcurrentStreams?: number;
maxHeaderListSize?: number;
initialWindowSize?: number;
maxFrameSize?: number;
}Usage Examples:
import { H2CClient } from 'undici';
// HTTP/2 cleartext connection
const h2cClient = new H2CClient('http://h2c-server.example.com');
// Make HTTP/2 requests
const { body } = await h2cClient.request({
path: '/api/data',
method: 'GET'
});
const data = await body.json();
await h2cClient.close();Utility for creating custom connection functions with TLS and socket options.
/**
* Build a custom connector function for establishing connections
* @param options - Connection configuration options
* @returns Connector function for creating connections
*/
function buildConnector(options?: ConnectorOptions): Connector;
type Connector = (options: ConnectOptions, callback: ConnectCallback) => void;
interface ConnectorOptions {
maxCachedSessions?: number;
socketPath?: string;
timeout?: number;
keepAlive?: boolean;
keepAliveInitialDelay?: number;
allowH2?: boolean;
maxHeaderListSize?: number;
maxConcurrentStreams?: number;
autoSelectFamily?: boolean;
autoSelectFamilyAttemptTimeout?: number;
}
interface ConnectOptions {
hostname: string;
host?: string;
port: number;
servername?: string;
httpSocket?: any;
}
type ConnectCallback = (err: Error | null, socket: any) => void;Usage Examples:
import { buildConnector, Client } from 'undici';
// Create a custom connector with specific options
const connector = buildConnector({
timeout: 30000,
keepAlive: true,
keepAliveInitialDelay: 1000,
allowH2: true,
autoSelectFamily: true
});
// Use connector with a client
const client = new Client('https://api.example.com', {
connect: connector
});
// Custom TLS connector
const tlsConnector = buildConnector({
timeout: 60000,
keepAlive: true,
maxCachedSessions: 100
});
// Use with Agent for multiple origins
const agent = new Agent({
connect: tlsConnector,
keepAliveTimeout: 30000
});type ConnectFunction = (options: ConnectOptions) => Promise<Duplex>;
interface ConnectOptions {
hostname: string;
host?: string;
port: number;
servername?: string;
timeout?: number;
}
interface BuildOptions {
ca?: string | Buffer | Array<string | Buffer>;
cert?: string | Buffer | Array<string | Buffer>;
key?: string | Buffer | Array<string | Buffer>;
secureOptions?: number;
rejectUnauthorized?: boolean;
}Install with Tessl CLI
npx tessl i tessl/npm-undici