Opinionated, caching, retrying fetch client for Node.js with enterprise-grade HTTP features
74
The primary fetch function that provides an enhanced, drop-in replacement for the standard Fetch API with additional enterprise features.
The core fetch function implements the standard Fetch API with additional make-fetch-happen features.
/**
* Enhanced fetch function with caching, retries, and proxy support
* @param {string|Request} url - URL string or Request object to fetch
* @param {FetchOptions} [options] - Request options with make-fetch-happen extensions
* @returns {Promise<Response>} Promise resolving to Response object
*/
function fetch(url, options);Usage Examples:
const fetch = require('make-fetch-happen');
// Basic GET request
const response = await fetch('https://api.example.com/users');
const users = await response.json();
// POST request with body
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Alice', email: 'alice@example.com' })
});
// Request with all enhanced features
const response = await fetch('https://api.example.com/data', {
// Caching
cachePath: './my-cache',
cache: 'default',
// Retries
retry: { retries: 3, factor: 2 },
onRetry: (cause) => console.log('Retrying due to:', cause.message),
// Security
integrity: 'sha256-abcd1234...',
strictSSL: true,
// Network
proxy: 'http://proxy.company.com:8080',
timeout: 30000
});Standard Request constructor re-exported from minipass-fetch.
/**
* HTTP request representation
* @param {string|Request} input - URL or existing Request
* @param {RequestInit} [init] - Request initialization options
*/
class Request {
constructor(input, init);
readonly url: string;
readonly method: string;
readonly headers: Headers;
body: any;
readonly redirect: string;
readonly referrer: string;
readonly referrerPolicy: string;
readonly mode: string;
readonly credentials: string;
readonly cache: string;
readonly integrity: string;
readonly keepalive: boolean;
readonly signal: AbortSignal;
clone(): Request;
arrayBuffer(): Promise<ArrayBuffer>;
blob(): Promise<Blob>;
json(): Promise<any>;
text(): Promise<string>;
}Standard Response constructor re-exported from minipass-fetch.
/**
* HTTP response representation
* @param {any} [body] - Response body
* @param {ResponseInit} [init] - Response initialization options
*/
class Response {
constructor(body, init);
readonly ok: boolean;
readonly status: number;
readonly statusText: string;
readonly headers: Headers;
readonly url: string;
readonly redirected: boolean;
readonly type: string;
body: ReadableStream;
readonly bodyUsed: boolean;
clone(): Response;
arrayBuffer(): Promise<ArrayBuffer>;
blob(): Promise<Blob>;
buffer(): Promise<Buffer>;
json(): Promise<any>;
text(): Promise<string>;
static error(): Response;
static redirect(url: string, status?: number): Response;
}Standard Headers constructor re-exported from minipass-fetch.
/**
* HTTP headers management
* @param {HeadersInit} [init] - Initial headers
*/
class Headers {
constructor(init);
append(name: string, value: string): void;
delete(name: string): void;
entries(): Iterator<[string, string]>;
forEach(callback: (value: string, name: string, headers: Headers) => void): void;
get(name: string): string | null;
has(name: string): boolean;
keys(): Iterator<string>;
set(name: string, value: string): void;
values(): Iterator<string>;
}Error class for fetch-related failures.
/**
* Error thrown by fetch operations
*/
class FetchError extends Error {
constructor(message: string, type: string, systemError?: object);
name: string;
message: string;
type: string;
code?: string;
errno?: string;
syscall?: string;
}Common error types:
'request-timeout': Request timed out'body-timeout': Request body timeout'system': System-level errors (network, DNS, etc.)'no-redirect': Redirect not allowed'no-location': Missing location header in redirect'max-redirect': Too many redirectsAll standard fetch options are supported:
/**
* Standard fetch options (subset of full FetchOptions)
*/
interface StandardFetchOptions {
method?: string; // HTTP method (GET, POST, etc.)
headers?: HeadersInit; // Request headers
body?: BodyInit; // Request body
redirect?: 'follow' | 'manual' | 'error'; // Redirect handling
timeout?: number; // Request timeout in milliseconds
size?: number; // Maximum response size
compress?: boolean; // Enable compression
follow?: number; // Maximum redirects to follow
}make-fetch-happen automatically sets certain request headers when they are not provided:
/**
* Automatically set request headers:
* - User-Agent: Set to "${package.name}/${package.version} (+https://npm.im/${package.name})"
* - Connection: Set to "keep-alive" if agent is used, "close" otherwise
*/Usage Examples:
// These headers are set automatically
const response = await fetch('https://api.example.com/data');
// User-Agent: make-fetch-happen/15.0.1 (+https://npm.im/make-fetch-happen)
// Connection: keep-alive (or close depending on agent configuration)
// Override automatic headers
const response2 = await fetch('https://api.example.com/data', {
headers: {
'User-Agent': 'MyApp/1.0',
'Connection': 'close'
}
});make-fetch-happen adds special headers to responses:
Added to cached responses (when cachePath is configured):
X-Local-Cache: Path to the cache directoryX-Local-Cache-Key: Unique cache key for this responseX-Local-Cache-Mode: Always 'stream'X-Local-Cache-Hash: Integrity hash of cached contentX-Local-Cache-Status: Cache status ('miss', 'hit', 'stale', 'revalidated', 'updated', 'skip')X-Local-Cache-Time: Cache insertion timestampAdded to all responses:
/**
* X-Fetch-Attempts header: Number of attempts made for this request
* - Starts at 1 for successful first attempt
* - Increments with each retry attempt
* - Present on all responses regardless of caching configuration
*/Usage Examples:
const response = await fetch('https://flaky-api.example.com/data', {
retry: { retries: 3 }
});
// Check how many attempts were made
const attempts = response.headers.get('x-fetch-attempts');
console.log(`Request completed after ${attempts} attempts`);
// For successful first attempt: x-fetch-attempts: "1"
// For request that succeeded on 3rd try: x-fetch-attempts: "3"Install with Tessl CLI
npx tessl i tessl/npm-make-fetch-happenevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9