rest.js HTTP Client
rest.js is an HTTP client library designed for both browser and Node.js environments, emphasizing extensibility through its interceptor-based architecture. It provides core functionality for making HTTP requests and normalizing request/response objects, with advanced features like MIME type conversion, error handling, and hypermedia API traversal implemented as composable interceptors. The current stable version is 2.0.0, which notably moved from a hard dependency on `when.js` to native ES6 Promises and completely dropped AMD module support. Releases historically occurred somewhat frequently for major feature additions in 1.x, with 2.0.0 being a significant breaking change. It allows developers to configure tailored HTTP clients by wrapping a basic client with only the necessary features, promoting a lightweight and modular approach to client-side HTTP interactions, differentiating it from monolithic HTTP libraries.
Common errors
-
TypeError: rest(...).then is not a function
cause Attempting to use rest.js v2.0.0 or later in an environment that does not natively support ES6 Promises, or where a global Promise object is not available.fixEnsure that a global ES6 `Promise` object is available. If targeting older environments, include a `Promise` polyfill (e.g., from `when.js` or `core-js`) before `rest.js` is loaded. -
ReferenceError: require is not defined
cause Trying to import `rest.js` (a CommonJS module) using `require()` syntax within an ES Module (ESM) context in Node.js or a browser environment without proper transpilation or bundling configuration.fixFor Node.js ESM projects, ensure compatibility layer or use dynamic `import('rest')`. For browser, use a bundler like Webpack/Rollup that handles CJS modules. Or, switch your file to CommonJS if possible. -
Error: Cannot find module 'rest/interceptor/entity'
cause Attempting to import or use the `rest/interceptor/entity` interceptor, which has been deprecated and effectively removed from active use.fixRemove the import for `rest/interceptor/entity` and discontinue its use. Access the parsed response entity directly via `response.entity()` instead. -
TypeError: client.chain is not a function
cause Calling `client.chain()` to compose interceptors when using a version of `rest.js` where this method has been deprecated.fixUpdate all instances of `client.chain()` to `client.wrap()` which is the preferred method for interceptor composition.
Warnings
- breaking Version 2.0.0 removed the hard dependency on `when.js` and now relies solely on the native ES6 Promise API. Users who relied on `when.js` specific features or polyfills must ensure their environment provides a global `Promise` or use a dedicated polyfill.
- breaking AMD (Asynchronous Module Definition) module support was completely removed in version 2.0.0. This affects users of AMD loaders like RequireJS or curl.js, who can no longer directly load rest.js as an AMD module.
- breaking The automatic path token parameter replacement feature was moved from core clients into the `rest/interceptor/params` interceptor, which itself is deprecated. This behavior is no longer applied automatically.
- deprecated The `rest/interceptor/entity` interceptor was deprecated. Its functionality is now available directly on the response object via `response.entity()`.
- deprecated The `client.chain()` method for composing interceptors was deprecated in favor of `client.wrap()`.
- gotcha For browser consumers, the recommended main module path changed from `rest/rest` to `rest/browser` to allow bundlers like Browserify and Webpack to better optimize the build.
Install
-
npm install rest -
yarn add rest -
pnpm add rest
Imports
- rest
import rest from 'rest';
const rest = require('rest'); - mime
import { mime } from 'rest/interceptor/mime';const mime = require('rest/interceptor/mime'); - errorCode
import errorCode from 'rest/interceptor/errorCode';
const errorCode = require('rest/interceptor/errorCode');
Quickstart
const rest = require('rest');
const mime = require('rest/interceptor/mime');
const errorCode = require('rest/interceptor/errorCode');
const defaultRequest = require('rest/interceptor/defaultRequest');
const pathPrefix = require('rest/interceptor/pathPrefix');
// Assume a base URL and an API key for a hypothetical service
const API_BASE_URL = 'https://api.example.com';
const API_KEY = process.env.MY_API_KEY ?? 'your-secret-api-key'; // Use process.env for robustness
// Configure a client with common interceptors
// pathPrefix to handle base URL
// defaultRequest to add common headers like Authorization
// mime to automatically parse JSON responses
// errorCode to handle HTTP error statuses gracefully
const client = rest
.wrap(pathPrefix, { prefix: API_BASE_URL })
.wrap(defaultRequest, {
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Accept': 'application/json'
}
})
.wrap(mime, { mime: 'application/json' })
.wrap(errorCode, { code: 400 }); // Treat 400 and above as errors
// Make a request to fetch user data
client({ path: '/users/123' }).then(
function(response) {
console.log('User data:', response.entity);
console.log('Status:', response.status.code);
},
function(error) {
console.error('Request failed:', error.entity || error.message);
console.error('Error status:', error.status && error.status.code);
}
);
// Example of a POST request
client({
path: '/users',
method: 'POST',
entity: { name: 'John Doe', email: 'john.doe@example.com' }
}).then(
function(response) {
console.log('New user created:', response.entity);
},
function(error) {
console.error('Failed to create user:', error.entity || error.message);
}
);