CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-undici

An HTTP/1.1 client, written from scratch for Node.js

Pending
Overview
Eval results
Files

connection-management.mddocs/

Connection Management

Dispatcher classes for managing HTTP connections at different scales, from single connections to multi-origin load balancing.

Capabilities

Client

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();

Pool

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();

BalancedPool

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

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();

ProxyAgent

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();

EnvHttpProxyAgent

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();

RetryAgent

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();

H2CClient

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();

Connection Builder

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
});

Types

Connection Types

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

docs

caching.md

connection-management.md

cookies.md

core-http.md

errors.md

global-config.md

headers-body.md

index.md

interceptors.md

mock-testing.md

web-standards.md

tile.json