RESTful HTTP client library with composable interceptor architecture for Node.js and browsers
76
Interceptors provide a composable middleware pattern for extending rest.js client functionality. They can transform requests, responses, or both, allowing you to add features like authentication, error handling, caching, and content negotiation.
Core interceptor creation and composition functionality.
const interceptor = require('rest/interceptor');
/**
* Create a custom interceptor
* @param {object} handlers - Interceptor handler functions
* @param {function} [handlers.init] - One-time initialization
* @param {function} [handlers.request] - Request transformation
* @param {function} [handlers.response] - Response transformation
* @param {function} [handlers.success] - Success response handler
* @param {function} [handlers.error] - Error response handler
* @param {Client} [handlers.client] - Default client to use
* @returns {Interceptor} Interceptor function
*/
function interceptor(handlers)
/**
* Complex request object for advanced interceptor scenarios
* @param {object} properties - Request properties
* @param {Request} properties.request - The request object
* @param {Promise} [properties.abort] - Abort promise
* @param {Client} [properties.client] - Override client
* @param {any} [properties.response] - Short-circuit response
*/
function ComplexRequest(properties)Usage Example:
const interceptor = require('rest/interceptor');
const customInterceptor = interceptor({
request: function(request, config, meta) {
// Transform request
request.headers = request.headers || {};
request.headers['X-Custom-Header'] = 'my-value';
return request;
},
response: function(response, config, meta) {
// Transform response
console.log('Response received:', response.status.code);
return response;
}
});
const client = rest.wrap(customInterceptor);HTTP Basic Authentication support.
const basicAuth = require('rest/interceptor/basicAuth');
/**
* Basic Auth interceptor configuration
* @param {object} config - Authentication config
* @param {string} config.username - Username
* @param {string} config.password - Password
*/Usage Example:
const basicAuth = require('rest/interceptor/basicAuth');
const client = rest.wrap(basicAuth, {
username: 'myuser',
password: 'mypassword'
});OAuth authentication interceptor.
const oAuth = require('rest/interceptor/oAuth');
/**
* OAuth interceptor for request signing
*/Automatic serialization/deserialization based on Content-Type.
const mime = require('rest/interceptor/mime');
/**
* MIME interceptor configuration
* @param {object} config - MIME config
* @param {string} [config.mime='text/plain'] - Default request MIME type
* @param {string} [config.accept] - Accept header value
* @param {Registry} [config.registry] - Custom MIME registry
* @param {boolean} [config.permissive=false] - Allow unknown MIME types
* @param {Client} [config.client] - Client for converter use
*/Extract response entity directly.
const entity = require('rest/interceptor/entity');
// Note: This interceptor is deprecated. Use response.entity() instead.Reject responses based on HTTP status codes.
const errorCode = require('rest/interceptor/errorCode');
/**
* Error code interceptor configuration
* @param {object} config - Error config
* @param {number} [config.code=400] - Minimum error status code
*/Usage Example:
const errorCode = require('rest/interceptor/errorCode');
const client = rest.wrap(errorCode, { code: 500 });
// Only reject on 500+ status codesAutomatically retry failed requests.
const retry = require('rest/interceptor/retry');
/**
* Retry interceptor for handling transient failures
*/Add request timeout handling.
const timeout = require('rest/interceptor/timeout');
/**
* Timeout interceptor configuration
* @param {object} config - Timeout config
* @param {number} config.timeout - Timeout in milliseconds
*/Add a prefix to all request paths.
const pathPrefix = require('rest/interceptor/pathPrefix');
/**
* Path prefix interceptor configuration
* @param {object} config - Prefix config
* @param {string} config.prefix - Path prefix to add
*/Usage Example:
const pathPrefix = require('rest/interceptor/pathPrefix');
const client = rest.wrap(pathPrefix, { prefix: '/api/v1' });
// Requests to '/users' become '/api/v1/users'URI template expansion using RFC 6570.
const template = require('rest/interceptor/template');
/**
* URI template interceptor for parameter expansion
*/Simple parameter replacement in URLs.
const params = require('rest/interceptor/params');
// Note: This interceptor is deprecated. Use template interceptor instead.Provide default values for request properties.
const defaultRequest = require('rest/interceptor/defaultRequest');
/**
* Default request interceptor configuration
* @param {object} config - Default request properties
*/Usage Example:
const defaultRequest = require('rest/interceptor/defaultRequest');
const client = rest.wrap(defaultRequest, {
headers: { 'User-Agent': 'MyApp/1.0' },
method: 'POST'
});Hypermedia support for following links and parsing Link headers according to RFC 5988.
const hateoas = require('rest/interceptor/hateoas');
/**
* HATEOAS interceptor configuration
* @param {object} config - HATEOAS config
* @param {string} [config.target=''] - Property to create on entity for links
* @param {Client} [config.client] - Client to use for following links
*/Usage Example:
const hateoas = require('rest/interceptor/hateoas');
const client = rest.wrap(hateoas);
client('/api/users/123').then(function(response) {
// Links are now accessible on the entity
if (response.entity.next) {
// Follow the 'next' relationship
return response.entity.next();
}
// Access link objects directly
console.log(response.entity.nextLink); // Link object reference
});Follow Location response headers.
const location = require('rest/interceptor/location');
/**
* Location interceptor configuration
* @param {object} config - Location config
* @param {number|function} [config.code] - Status codes to follow
*/JSONP support for cross-origin requests.
const jsonp = require('rest/interceptor/jsonp');
/**
* JSONP interceptor for cross-origin requests
* @param {object} config - JSONP config
* @param {string} [config.callback] - Callback parameter name
*/Cross-Site Request Forgery protection.
const csrf = require('rest/interceptor/csrf');
/**
* CSRF protection interceptor
*/Interceptors can be chained together to create complex client behaviors:
const mime = require('rest/interceptor/mime');
const basicAuth = require('rest/interceptor/basicAuth');
const errorCode = require('rest/interceptor/errorCode');
const pathPrefix = require('rest/interceptor/pathPrefix');
const client = rest
.wrap(pathPrefix, { prefix: '/api/v1' })
.wrap(basicAuth, { username: 'user', password: 'pass' })
.wrap(mime)
.wrap(errorCode, { code: 400 });
// This client will:
// 1. Add '/api/v1' prefix to all paths
// 2. Add Basic Auth headers
// 3. Handle MIME type conversion
// 4. Reject responses with status >= 400Create custom interceptors for specialized functionality:
const interceptor = require('rest/interceptor');
const loggingInterceptor = interceptor({
init: function(config) {
config.logLevel = config.logLevel || 'info';
return config;
},
request: function(request, config) {
console.log(`[${config.logLevel}] Request:`, request.method, request.path);
return request;
},
response: function(response, config) {
console.log(`[${config.logLevel}] Response:`, response.status.code);
return response;
},
error: function(response, config) {
console.error(`[${config.logLevel}] Error:`, response.status.code);
// Return rejected promise to maintain error state
return Promise.reject(response);
}
});
const client = rest.wrap(loggingInterceptor, { logLevel: 'debug' });Install with Tessl CLI
npx tessl i tessl/npm-restevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10