An HTTP/1.1 client, written from scratch for Node.js
—
Global settings for default dispatchers, origins, and Web API installation to configure undici behavior across your entire application.
Configure a default dispatcher that will be used for all undici requests when no specific dispatcher is provided.
/**
* Set global dispatcher for all requests
* @param dispatcher - Dispatcher instance to use globally
*/
function setGlobalDispatcher(dispatcher: Dispatcher): void;
/**
* Get current global dispatcher
* @returns Current global dispatcher instance
*/
function getGlobalDispatcher(): Dispatcher;Usage Examples:
import { setGlobalDispatcher, getGlobalDispatcher, Agent, Pool } from 'undici';
// Set a global agent with custom configuration
const globalAgent = new Agent({
factory: (origin, opts) => {
return new Pool(origin, {
...opts,
connections: 10,
keepAliveTimeout: 60000,
keepAliveMaxTimeout: 600000
});
}
});
setGlobalDispatcher(globalAgent);
// All subsequent requests use the global agent
const response1 = await fetch('https://api.example.com/users');
const response2 = await fetch('https://another-api.example.com/data');
// Check current global dispatcher
const currentDispatcher = getGlobalDispatcher();
console.log(currentDispatcher === globalAgent); // true
// Configure global agent with interceptors
import { interceptors } from 'undici';
const enhancedAgent = new Agent()
.compose(
interceptors.retry({ maxRetries: 3 }),
interceptors.redirect({ maxRedirections: 5 }),
interceptors.decompress()
);
setGlobalDispatcher(enhancedAgent);
// All requests now have retry, redirect, and decompression
const response = await fetch('https://api.example.com/data');Set a global origin for the fetch API to resolve relative URLs consistently across your application.
/**
* Set global origin for fetch API
* @param origin - Base origin URL for resolving relative URLs
*/
function setGlobalOrigin(origin: string | URL): void;
/**
* Get current global origin
* @returns Current global origin or undefined
*/
function getGlobalOrigin(): string | undefined;Usage Examples:
import { setGlobalOrigin, getGlobalOrigin, fetch } from 'undici';
// Set global origin for API base URL
setGlobalOrigin('https://api.example.com');
// Relative URLs are resolved against the global origin
const response1 = await fetch('/users'); // → https://api.example.com/users
const response2 = await fetch('/posts/123'); // → https://api.example.com/posts/123
const response3 = await fetch('./data.json'); // → https://api.example.com/data.json
// Absolute URLs override the global origin
const response4 = await fetch('https://other-api.com/data'); // → https://other-api.com/data
// Check current global origin
console.log(getGlobalOrigin()); // 'https://api.example.com'
// Update global origin for different environments
const isProduction = process.env.NODE_ENV === 'production';
const apiOrigin = isProduction
? 'https://api.production.com'
: 'https://api.development.com';
setGlobalOrigin(apiOrigin);
// Environment-specific API calls
const userData = await fetch('/user/profile');
const settings = await fetch('/user/settings');Install undici's Web API implementations globally to make them available throughout your application without imports.
/**
* Install Web APIs globally on globalThis
* Makes fetch, Headers, Request, Response, FormData, WebSocket, etc. available globally
*/
function install(): void;Usage Examples:
import { install } from 'undici';
// Install all Web APIs globally
install();
// Now you can use Web APIs without importing
// These are now available globally:
// Fetch API
const response = await fetch('https://api.example.com/data');
const data = await response.json();
// Headers API
const headers = new Headers({
'Content-Type': 'application/json',
'Authorization': 'Bearer token123'
});
// Request/Response API
const request = new Request('https://api.example.com/users', {
method: 'POST',
headers,
body: JSON.stringify({ name: 'Alice' })
});
const customResponse = new Response(JSON.stringify({ success: true }), {
status: 201,
headers: { 'content-type': 'application/json' }
});
// FormData API
const formData = new FormData();
formData.append('file', fileBuffer, 'document.pdf');
formData.append('description', 'Important document');
// WebSocket API
const ws = new WebSocket('wss://api.example.com/socket');
ws.onopen = () => console.log('WebSocket connected');
ws.onmessage = (event) => console.log('Message:', event.data);
// EventSource API
const eventSource = new EventSource('https://api.example.com/events');
eventSource.onmessage = (event) => {
console.log('Event:', JSON.parse(event.data));
};
// WebSocket Events
ws.addEventListener('close', (event) => {
if (event instanceof CloseEvent) {
console.log(`WebSocket closed: ${event.code} ${event.reason}`);
}
});import {
setGlobalDispatcher,
setGlobalOrigin,
install,
Agent,
interceptors,
cacheStores
} from 'undici';
function configureUndici() {
const isDevelopment = process.env.NODE_ENV === 'development';
const isProduction = process.env.NODE_ENV === 'production';
// Install Web APIs globally
install();
// Set environment-specific API origin
const apiOrigin = process.env.API_BASE_URL || (
isProduction
? 'https://api.production.com'
: 'http://localhost:3001'
);
setGlobalOrigin(apiOrigin);
// Configure global dispatcher based on environment
const interceptorChain = [];
// Always enable decompression
interceptorChain.push(interceptors.decompress());
// Enable caching in production
if (isProduction) {
interceptorChain.push(interceptors.cache({
store: new cacheStores.MemoryCacheStore(),
methods: ['GET', 'HEAD'],
cacheByDefault: 300 // 5 minutes
}));
}
// Enable request logging in development
if (isDevelopment) {
interceptorChain.push(interceptors.dump({
request: true,
response: true,
requestHeaders: true,
responseHeaders: true,
logger: console.log
}));
}
// Always enable retries and redirects
interceptorChain.push(
interceptors.retry({
maxRetries: isProduction ? 3 : 1,
methods: ['GET', 'HEAD', 'OPTIONS'],
statusCodes: [408, 413, 429, 500, 502, 503, 504]
}),
interceptors.redirect({ maxRedirections: 5 })
);
// Create and set global agent
const globalAgent = new Agent({
factory: (origin, opts) => {
return new Pool(origin, {
...opts,
connections: isProduction ? 10 : 5,
keepAliveTimeout: 60000,
keepAliveMaxTimeout: 600000,
bodyTimeout: 30000,
headersTimeout: 10000
});
}
}).compose(...interceptorChain);
setGlobalDispatcher(globalAgent);
console.log(`Undici configured for ${process.env.NODE_ENV} environment`);
console.log(`API Origin: ${apiOrigin}`);
}
// Call during application startup
configureUndici();import {
setGlobalDispatcher,
MockAgent,
install
} from 'undici';
function configureUndiciForTesting() {
// Install Web APIs for test compatibility
install();
// Create mock agent for testing
const mockAgent = new MockAgent();
// Disable real network connections in tests
mockAgent.disableNetConnect();
// Allow connections to test servers if needed
if (process.env.TEST_SERVER_URL) {
mockAgent.enableNetConnect(process.env.TEST_SERVER_URL);
}
// Set as global dispatcher
setGlobalDispatcher(mockAgent);
return mockAgent;
}
// In test setup
const mockAgent = configureUndiciForTesting();
// In individual tests
const mockPool = mockAgent.get('https://api.example.com');
mockPool.intercept({ path: '/users', method: 'GET' })
.reply(200, [{ id: 1, name: 'Test User' }]);import {
setGlobalDispatcher,
ProxyAgent,
EnvHttpProxyAgent
} from 'undici';
function configureProxy() {
// Option 1: Explicit proxy configuration
if (process.env.HTTP_PROXY_URL) {
const proxyAgent = new ProxyAgent({
uri: process.env.HTTP_PROXY_URL,
auth: process.env.HTTP_PROXY_AUTH, // username:password
token: process.env.HTTP_PROXY_TOKEN
});
setGlobalDispatcher(proxyAgent);
console.log(`Using explicit proxy: ${process.env.HTTP_PROXY_URL}`);
return;
}
// Option 2: Environment-based proxy (HTTP_PROXY, HTTPS_PROXY, NO_PROXY)
if (process.env.HTTP_PROXY || process.env.HTTPS_PROXY) {
const envProxyAgent = new EnvHttpProxyAgent();
setGlobalDispatcher(envProxyAgent);
console.log('Using environment-based proxy configuration');
return;
}
console.log('No proxy configuration found');
}
// Configure proxy during application startup
configureProxy();import {
setGlobalDispatcher,
setGlobalOrigin,
install,
Agent,
Pool,
interceptors,
buildConnector,
cacheStores
} from 'undici';
import { readFileSync } from 'fs';
function advancedUndiciConfiguration() {
// Install Web APIs
install();
// Custom TLS configuration
const tlsOptions = {
ca: process.env.CUSTOM_CA_CERT ? readFileSync(process.env.CUSTOM_CA_CERT) : undefined,
cert: process.env.CLIENT_CERT ? readFileSync(process.env.CLIENT_CERT) : undefined,
key: process.env.CLIENT_KEY ? readFileSync(process.env.CLIENT_KEY) : undefined,
rejectUnauthorized: process.env.NODE_ENV === 'production'
};
// Custom connector with TLS options
const connector = buildConnector(tlsOptions);
// Advanced agent configuration
const agent = new Agent({
factory: (origin, opts) => {
const poolOptions = {
...opts,
connections: parseInt(process.env.HTTP_POOL_SIZE) || 10,
keepAliveTimeout: parseInt(process.env.HTTP_KEEP_ALIVE_TIMEOUT) || 60000,
keepAliveMaxTimeout: parseInt(process.env.HTTP_KEEP_ALIVE_MAX_TIMEOUT) || 600000,
bodyTimeout: parseInt(process.env.HTTP_BODY_TIMEOUT) || 30000,
headersTimeout: parseInt(process.env.HTTP_HEADERS_TIMEOUT) || 10000,
maxHeaderSize: parseInt(process.env.HTTP_MAX_HEADER_SIZE) || 16384,
connect: connector
};
return new Pool(origin, poolOptions);
},
interceptors: {
Agent: [
// Global interceptors applied to all requests
interceptors.dns({
maxItems: 100,
maxTtl: 300000 // 5 minutes DNS cache
})
]
}
});
// Compose with additional interceptors
const configuredAgent = agent.compose(
// Response caching
interceptors.cache({
store: process.env.REDIS_URL
? new CustomRedisCacheStore(process.env.REDIS_URL)
: new cacheStores.MemoryCacheStore(),
methods: ['GET', 'HEAD'],
cacheByDefault: 300
}),
// Request/response compression
interceptors.decompress(),
// Automatic redirects
interceptors.redirect({
maxRedirections: parseInt(process.env.HTTP_MAX_REDIRECTS) || 5
}),
// Retry logic
interceptors.retry({
maxRetries: parseInt(process.env.HTTP_MAX_RETRIES) || 3,
maxTimeout: parseInt(process.env.HTTP_RETRY_MAX_TIMEOUT) || 30000,
methods: ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE'],
statusCodes: [408, 413, 429, 500, 502, 503, 504],
errorCodes: ['ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ENETDOWN']
}),
// Enhanced error handling
interceptors.responseError({
throwOnError: process.env.HTTP_THROW_ON_ERROR === 'true',
statusCodes: [400, 401, 403, 404, 500, 502, 503, 504],
includeResponseBody: true,
maxResponseBodySize: 1024
})
);
// Set global configuration
setGlobalDispatcher(configuredAgent);
if (process.env.API_BASE_URL) {
setGlobalOrigin(process.env.API_BASE_URL);
}
console.log('Advanced undici configuration applied');
}
// Initialize during application startup
advancedUndiciConfiguration();Use environment variables for configuration:
# .env file
NODE_ENV=production
API_BASE_URL=https://api.production.com
HTTP_PROXY=http://proxy.company.com:8080
HTTP_POOL_SIZE=20
HTTP_KEEP_ALIVE_TIMEOUT=120000
HTTP_MAX_RETRIES=5Properly close global dispatcher during application shutdown:
import { getGlobalDispatcher } from 'undici';
process.on('SIGTERM', async () => {
console.log('Shutting down gracefully...');
const dispatcher = getGlobalDispatcher();
if (dispatcher && typeof dispatcher.close === 'function') {
await dispatcher.close();
}
process.exit(0);
});Monitor global dispatcher health:
import { getGlobalDispatcher } from 'undici';
async function healthCheck() {
try {
const dispatcher = getGlobalDispatcher();
// Test with a lightweight request
const response = await fetch('/health', {
method: 'HEAD',
dispatcher // Use specific dispatcher for health check
});
return response.ok;
} catch (error) {
console.error('Health check failed:', error.message);
return false;
}
}
// Run health checks periodically
setInterval(async () => {
const isHealthy = await healthCheck();
console.log(`HTTP client health: ${isHealthy ? 'OK' : 'FAIL'}`);
}, 30000);Install with Tessl CLI
npx tessl i tessl/npm-undici