Making Requests
Rezo provides named methods for every standard HTTP method. Methods without a request body take (url, options?). Methods with a body take (url, data, options?). Each body method also has typed variants for JSON, form-encoded, and multipart data.
Importing
import rezo from 'rezo'; The default export is a pre-configured instance with the HTTP adapter. You can also create custom instances (see Instances).
Methods Without a Body
These methods accept (url, options?) and never send a request body.
GET
// Simple GET
const response = await rezo.get('https://api.example.com/users');
console.log(response.data);
// GET with query parameters
const response = await rezo.get('https://api.example.com/users', {
params: { page: 2, limit: 10, role: 'admin' }
});
// GET with typed response
const response = await rezo.get<User[]>('https://api.example.com/users');
// response.data is typed as User[]
// GET with custom headers and timeout
const response = await rezo.get('https://api.example.com/users', {
headers: { Authorization: 'Bearer token123' },
timeout: 5000
}); HEAD
Returns only the response headers. The response body is empty.
const response = await rezo.head('https://api.example.com/users');
console.log(response.headers.get('content-length'));
console.log(response.headers.get('last-modified')); OPTIONS
Used for CORS preflight checks or discovering supported methods.
const response = await rezo.options('https://api.example.com/users');
console.log(response.headers.get('allow'));
// "GET, POST, PUT, DELETE, OPTIONS" TRACE
Echoes back the received request. Primarily used for debugging.
const response = await rezo.trace('https://api.example.com/debug'); DELETE
Sends a request with no body. For APIs that expect a body on DELETE, use rezo.request().
const response = await rezo.delete('https://api.example.com/users/42');
console.log(response.status); // 204
// DELETE with query parameters
const response = await rezo.delete('https://api.example.com/cache', {
params: { key: 'user:42' }
}); Methods With a Body
These methods accept (url, data, options?) and send the data as the request body.
POST
The basic post method sends data as-is. Rezo auto-detects the content type from the data provided.
// POST with auto-detected content type
const response = await rezo.post('https://api.example.com/users', {
name: 'Alice',
email: 'alice@example.com'
}); PUT
Replaces a resource entirely.
const response = await rezo.put('https://api.example.com/users/42', {
name: 'Alice Updated',
email: 'alice@example.com',
role: 'admin'
}); PATCH
Partially updates a resource.
const response = await rezo.patch('https://api.example.com/users/42', {
role: 'admin'
}); Typed Body Variants
Every body method (post, put, patch) has three typed variants that explicitly set the Content-Type header and handle serialization.
postJson / putJson / patchJson
Serializes the data as JSON and sets Content-Type: application/json.
// POST JSON
const response = await rezo.postJson('https://api.example.com/users', {
name: 'Alice',
email: 'alice@example.com'
});
// PUT JSON with typed response
const response = await rezo.putJson<User>('https://api.example.com/users/42', {
name: 'Alice',
role: 'admin'
});
// PATCH JSON
const response = await rezo.patchJson('https://api.example.com/users/42', {
role: 'admin'
});
// JSON arrays are also supported
await rezo.postJson('https://api.example.com/batch', [
{ action: 'create', name: 'Alice' },
{ action: 'create', name: 'Bob' }
]);
// Strings that are already JSON
await rezo.postJson('https://api.example.com/data', '{"key":"value"}'); postForm / putForm / patchForm
Serializes the data as URL-encoded form data and sets Content-Type: application/x-www-form-urlencoded.
// POST form data
const response = await rezo.postForm('https://api.example.com/login', {
username: 'alice',
password: 'secret123'
});
// PUT form data
await rezo.putForm('https://api.example.com/settings', {
theme: 'dark',
language: 'en'
});
// Also accepts URLSearchParams
const params = new URLSearchParams();
params.set('grant_type', 'authorization_code');
params.set('code', 'abc123');
await rezo.postForm('https://auth.example.com/token', params);
// Or a pre-encoded string
await rezo.postForm('https://api.example.com/data', 'key=value&foo=bar'); postMultipart / putMultipart / patchMultipart
Sends data as multipart/form-data, handling boundary generation automatically. Ideal for file uploads.
import { RezoFormData } from 'rezo';
// From a plain object
await rezo.postMultipart('https://api.example.com/upload', {
name: 'profile-photo',
file: someBuffer
});
// From RezoFormData
const form = new RezoFormData();
form.append('title', 'My Document');
form.append('file', buffer, { filename: 'doc.pdf', contentType: 'application/pdf' });
await rezo.postMultipart('https://api.example.com/documents', form);
// From native FormData (browser or Node.js 18+)
const nativeForm = new FormData();
nativeForm.append('name', 'test');
nativeForm.append('file', blob);
await rezo.postMultipart('https://api.example.com/upload', nativeForm);
// PUT multipart
await rezo.putMultipart('https://api.example.com/avatar', {
image: avatarBuffer
}); The Generic request() Method
For full control over the request, use request(). It accepts a single configuration object.
const response = await rezo.request({
url: 'https://api.example.com/users',
method: 'POST',
headers: { 'X-Custom-Header': 'value' },
body: JSON.stringify({ name: 'Alice' }),
timeout: 10000,
responseType: 'json'
});
// DELETE with a body (not supported by rezo.delete directly)
const response = await rezo.request({
url: 'https://api.example.com/batch',
method: 'DELETE',
body: JSON.stringify({ ids: [1, 2, 3] }),
headers: { 'Content-Type': 'application/json' }
}); Callable Instance
The default rezo export is also callable as a function, following the Fetch API pattern.
// GET (default method)
const response = await rezo('https://api.example.com/users');
// POST with Fetch-style options
const response = await rezo('https://api.example.com/users', {
method: 'POST',
body: JSON.stringify({ name: 'Alice' }),
headers: { 'Content-Type': 'application/json' }
});
// Using Rezo's json shorthand in callable form
const response = await rezo('https://api.example.com/users', {
method: 'POST',
json: { name: 'Alice' }
});
// Using form shorthand
const response = await rezo('https://api.example.com/login', {
method: 'POST',
form: { username: 'alice', password: 'secret' }
}); Streaming, Downloads, and Uploads
These methods return event emitters instead of awaiting a full response.
stream()
Returns a RezoStreamResponse that emits data chunks as they arrive.
const stream = rezo.stream('https://example.com/large-file');
stream.on('data', (chunk) => {
console.log('Received:', chunk.length, 'bytes');
});
stream.on('headers', (info) => {
console.log('Status:', info.status);
console.log('Content-Type:', info.headers.get('content-type'));
});
stream.on('progress', (p) => {
console.log(`${p.percent}% complete`);
});
stream.on('finish', (info) => {
console.log('Stream complete. Total bytes:', info.totalBytes);
});
stream.on('error', (err) => {
console.error('Stream error:', err.message);
}); download()
Downloads a resource directly to a file. Returns a RezoDownloadResponse with progress events.
const download = rezo.download(
'https://example.com/file.zip',
'./downloads/file.zip'
);
download.on('progress', (p) => {
console.log(`${p.percent}% downloaded (${p.transferred} / ${p.total} bytes)`);
});
download.on('finish', (info) => {
console.log('Saved to:', info.filePath);
console.log('Total size:', info.totalBytes);
});
download.on('error', (err) => {
console.error('Download failed:', err.message);
}); upload()
Uploads data with progress tracking. Returns a RezoUploadResponse.
import { readFileSync } from 'node:fs';
const fileBuffer = readFileSync('./large-file.bin');
const upload = rezo.upload('https://api.example.com/upload', fileBuffer);
upload.on('progress', (p) => {
console.log(`${p.percent}% uploaded`);
});
upload.on('finish', (info) => {
console.log('Upload complete. Server responded:', info.status);
});
upload.on('error', (err) => {
console.error('Upload failed:', err.message);
}); Pagination
Rezo provides a built-in async iterator for paginated APIs.
// Auto-detect pagination from Link headers
for await (const page of rezo.paginate('https://api.example.com/users')) {
console.log(page); // response.data for each page
}
// Cursor-based pagination
for await (const page of rezo.paginate('https://api.example.com/items', {
pagination: {
getNextUrl: (resp) => resp.data.next_cursor
? `/items?cursor=${resp.data.next_cursor}`
: null
}
})) {
console.log(page);
}
// Collect all items with a transform
const allUsers = [];
for await (const items of rezo.paginate('/users', {
pagination: {
transform: (resp) => resp.data.results,
requestLimit: 10 // Stop after 10 pages
}
})) {
allUsers.push(...items);
}