Adapters

Adapters Overview

Rezo uses an adapter pattern to support different JavaScript runtimes. Each adapter is a platform-specific HTTP implementation that conforms to a unified interface. This means your application code stays the same regardless of whether it runs on Node.js, a browser, Deno, Bun, React Native, or an edge runtime like Cloudflare Workers.

What is an Adapter?

An adapter is a module that translates Rezo’s internal request configuration into a platform-native HTTP call. Every adapter implements the same executeRequest function signature:

type ExecuteRequestFn<T = any> = (
  options: RezoRequestConfig,
  defaultOptions: RezoDefaultOptions,
  jar: RezoCookieJar
) => Promise<RezoResponse<T> | RezoStreamResponse | RezoDownloadResponse | RezoUploadResponse>;

This unified interface guarantees that features like cookie jars, retries, redirect handling, and response caching behave consistently across all adapters that support them.

Available Adapters

Rezo ships with six adapters, each optimized for a specific runtime or use case:

AdapterRuntimeImport Path
HTTPNode.js, Bunrezo/adapters/http
HTTP/2Node.js, Bunrezo/adapters/http2
FetchBrowsers, Deno, Bun, Edgerezo/adapters/fetch
XHRBrowsers (legacy)rezo/adapters/xhr
cURLNode.js (shell)rezo/adapters/curl
React NativeReact Native, Exporezo/adapters/react-native

Automatic Selection

When you import Rezo from the main entry point (import rezo from 'rezo'), the adapter picker automatically detects your runtime environment and selects the best adapter for each request. The selection logic lives in src/adapters/picker.ts and works in three stages.

1. Runtime Detection

The picker identifies the current environment by checking for platform-specific globals:

import { detectRuntime } from 'rezo/adapters';

const runtime = detectRuntime();
// {
//   isNode: true,
//   isBrowser: false,
//   isDeno: false,
//   isBun: false,
//   isReactNative: false,
//   isEdge: false,
//   isWebWorker: false,
//   isElectronMain: false,
//   isElectronRenderer: false
// }

Detection order matters — React Native is checked before browser (since both have navigator), and Bun is checked before Node.js (since Bun sets process.versions.node for compatibility).

2. Capability Scoring

Each adapter is scored against the request’s requirements. Hard requirements (like needing proxy or cookie jar support) disqualify adapters that lack them. Soft requirements (like streaming or progress tracking) add bonus points.

import { getAdapterDiagnostics } from 'rezo/adapters';

const diagnostics = getAdapterDiagnostics(requestConfig, defaultOptions);
console.log(diagnostics.scores);
// [
//   { adapter: 'http', score: 140 },
//   { adapter: 'http2', score: 138 },
//   { adapter: 'curl', score: 134 },
//   { adapter: 'fetch', score: 105 }
// ]

3. Selection Priority by Environment

The picker narrows candidates based on environment, then picks the highest-scoring adapter:

EnvironmentAvailable Adapters (priority order)
Node.js / Bun / Electronhttp, http2, curl, fetch
Browser / Web Workerfetch, xhr
Denofetch, http
React Nativereact-native, fetch
Edge (Cloudflare Workers, Vercel Edge)fetch

Manual Selection

For tree-shaking and explicit control, import the adapter-specific entry point directly. This is the recommended approach for production applications:

// Node.js -- full-featured HTTP adapter
import rezo from 'rezo/adapters/http';

// HTTP/2 multiplexing
import rezo from 'rezo/adapters/http2';

// Browser -- minimal bundle
import rezo from 'rezo/adapters/fetch';

// Legacy browser support
import rezo from 'rezo/adapters/xhr';

// Shell-based cURL execution
import rezo from 'rezo/adapters/curl';

// React Native / Expo
import rezo from 'rezo/adapters/react-native';

Each entry point exports a pre-configured rezo default instance plus the Rezo class, RezoError, RezoHeaders, RezoFormData, and RezoCookieJar — everything you need without pulling in unused adapters.

import rezo, { Rezo, RezoError, RezoHeaders } from 'rezo/adapters/http';

// Use the default instance
const { data } = await rezo.get('https://api.example.com/users');

// Or create a custom instance
const client = new Rezo({
  baseURL: 'https://api.example.com',
  timeout: 10000
});

Custom Adapter Picker

You can override the automatic selection with a custom picker function:

import { createAdapterPicker } from 'rezo/adapters';

// Always use a specific adapter
const picker = createAdapterPicker({ adapter: 'http2' });

// Custom logic based on request context
const picker = createAdapterPicker({
  customPicker: (context, runtime) => {
    if (context.needsHttp2) return 'http2';
    if (context.needsProxy) return 'http';
    return 'fetch';
  },
  debug: true // logs selection decisions
});

Capabilities Matrix

Not all adapters support all features. This matrix shows what each adapter provides:

CapabilityHTTPHTTP/2FetchXHRcURLReact Native
Cookie JarYesYesNoNoYesNo
Proxy (HTTP/HTTPS/SOCKS)YesYesNoNoYesNo
Response StreamingYesYesYesNoYesYes
HTTP/2 ProtocolNoYesNoNoYesNo
Upload ProgressYesYesNoYesYesNo
Download ProgressYesYesYesYesYesYes
File DownloadYesYesNoNoYesYes
CompressionYesYesYesNoYesYes
Abort SignalYesYesYesYesYesYes
TLS ConfigurationYesYesNoNoYesNo

The picker uses this matrix internally. When a request requires cookies and proxy support, only HTTP, HTTP/2, and cURL remain eligible. The picker then scores the eligible adapters and selects the best match.

Adapter Caching

Loaded adapter modules are cached in memory so that repeated requests do not re-import the module. You can clear this cache if needed (useful in testing or hot-reload scenarios):

import { clearAdapterCache } from 'rezo/adapters';

clearAdapterCache();

Choosing the Right Adapter

  • HTTP — Best for Node.js server-side applications. Full feature set, connection pooling, TLS fingerprinting, staged timeouts, and socket telemetry.
  • HTTP/2 — Best when you need multiplexed streams to the same origin. Session pooling with automatic GOAWAY handling.
  • Fetch — Best for browsers, Deno, and edge runtimes. Smallest bundle size. Use when you do not need proxy or cookie jar support.
  • XHR — Best for legacy browser compatibility (IE11+). Provides upload/download progress where Fetch cannot.
  • cURL — Best for debugging, scripting, or when you need protocol features only cURL provides (FTP, SMTP, advanced TLS, DNS-over-HTTPS).
  • React Native — Best for mobile apps. Handles native Blob/FormData and detects Expo environments.