Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
rest-facade
Advanced tools
The rest-facade npm package is a lightweight library that simplifies the process of making RESTful API calls. It provides a facade over HTTP requests, making it easier to interact with REST APIs by abstracting away the complexities of handling HTTP methods, headers, and responses.
Creating a REST client
This feature allows you to create a REST client that can be used to interact with a RESTful API. The `Client` class takes the base URL of the API as a parameter.
const { Client } = require('rest-facade');
const api = new Client('https://api.example.com');
Making GET requests
This feature allows you to make GET requests to a specified endpoint. The `get` method returns a promise that resolves with the response data or rejects with an error.
api.get('/resource').then(response => console.log(response)).catch(error => console.error(error));
Making POST requests
This feature allows you to make POST requests to a specified endpoint with a payload. The `create` method sends the payload to the server and returns a promise that resolves with the response data or rejects with an error.
api.create('/resource', { key: 'value' }).then(response => console.log(response)).catch(error => console.error(error));
Handling headers
This feature allows you to include custom headers in your requests. The headers can be specified as an option in the request method.
api.get('/resource', { headers: { 'Authorization': 'Bearer token' } }).then(response => console.log(response)).catch(error => console.error(error));
Error handling
This feature provides a way to handle errors that occur during the request. The promise returned by the request method can be caught to handle any errors.
api.get('/resource').then(response => console.log(response)).catch(error => console.error('Error:', error.message));
Axios is a popular promise-based HTTP client for the browser and Node.js. It provides a simple API for making HTTP requests and supports features like interceptors, automatic JSON transformation, and request cancellation. Compared to rest-facade, Axios offers more advanced features and greater flexibility.
Request is a simplified HTTP client for Node.js. It is designed to be easy to use and supports features like cookies, redirects, and multipart form data. While request is more feature-rich, it is also more complex than rest-facade. Note that the request package is now deprecated.
Node-fetch is a lightweight module that brings the Fetch API to Node.js. It is minimalistic and focuses on providing a simple API for making HTTP requests. Compared to rest-facade, node-fetch is more low-level and requires more manual handling of requests and responses.
Node.js module that abstracts the process of consuming a REST endpoint.
npm install rest-facade
When creating a new client, a URL must be given as first arguments. If the URL have dynamic params, those variable params must be marked with the colon notation, as shown below.
var rest = require('rest-facade');
var options = {
headers: {
Authorization: 'Bearer token'
},
errorFormatter: {
name: 'error.title',
message: 'error.text',
}
};
var Users = new rest.Client('http://domain.com/users/:id', options);
// The URL can have several dynamic params.
var UserVideos = new rest.Client('http://domain.com/users/:userId/videos/:slug');
The getAll()
method can take an optional object as first parameters specifying the URL params. Considering the UserVideos model from last example:
// Retrieve all videos from the user with ID 4.
// This will resolve to a "GET http://domain.com/users/4/videos" request.
UserVideos
.getAll({ userId: 4 })
.then(function (videos) {
console.log(videos.length, 'videos retrieved');
});
// Retrieve the user with ID 4.
Users
.get({ id: 4 })
.then(function (user) {
console.log(user);
});
The create method can be called using several signatures.
create(data)
returns a Promise.create(urlParams, data)
returns a Promise.create(data, callback)
doesn't return a promise.create(urlParams, data, callback)
doesn't return a promise.Users
.create({ firstName: 'John', lastName: 'Doe' });
.then(function (user) {
console.log('User created');
});
UserVideos
.create({ userId: 4 }, { title: 'Learning Javascript', slug: 'learn-javascript' })
.then(function (video) {
console.log('User video created');
}):
As it was the case with the create()
method, delete()
can also be called with different signatures.
delete(urlParams)
returns a Promise.delete(callback)
returns a Promise.delete(urlParams, callback)
doesn't return a Promise.Users
.delete({ id: userId })
.then(function () {
console.log('User deleted');
});
// This will resolve to: DELETE http://domain.com/users/videos/learn-javascript
UserVideos
.delete({ slug: 'learn-javascript' })
.then(function () {
// ...
});
There are 2 ways to update data, if you are using correctly the HTTP methods, 1 is PUT and the other one is PATCH, rest-facade supports both of them:Client.update
and Client.patch
.
As with the previous methods, an object with the URL parameters must be provided as first argument. The second argument must be an object with the new data.
Users
.update({ id: userId }, data)
.then(function () {
console.log('User updated');
});
or
Users
.put({ id: userId }, data)
.then(function () {
console.log('User updated');
});
Users
.patch({ id: userId }, data)
.then(function () {
console.log('User updated');
});
Both functions work exactly the same, the only difference is the method used to perform the request.
In case you don't want to use the all the fancy abstractions (create
, update
, delete
, getAll
) you can also send plain HTTP requests using the HTTP method function.
// GET request.
Users.get(qsParams[, cb]);
// POST request.
Users.post(qsParams, data[, cb]);
// PUT request.
Users.put(qsParams, data[, cb]);
// PATCH request.
Users.patch(qsParams, data[, cb]);
// DELETE request.
Users.delete(qsParams[, data, cb]);
All methods support callbacks. However, if a callback function is given no promise will be returned. Callbacks must always be provided after all other function arguments. E.g.:
Users.getAll(function (err, users) {
console.log(users.length, 'users found');
});
Users.getAll(function (err, body, headers) {
// ...
});
All methods accept an object with URL params as first argument. The properties in this object will be used to format the URL as shown above. However, the properties defined in this object, but not in the endpoint URL, will be added as query string params.
N.B. any properties in a given
options
object whose values are Functions will be ignored with regard to generating the query string.
var Users = new rest.Client('http://domain.com/users/:id');
Users.get({ id: 1 }); // Resolves to http://domain.com/users/1
Users.getAll({ page: 1, pageSize: 10 }); // Resolves to http://domain.com/users?page=1&pageSize=10
There may be some cases when you are working with an API that follows a different naming convention, and it is not really clean to have mixed naming conventions in our code.
// Not good.
Users.getAll({ page: 1, 'page_size': 10 });
You can solve this problem by specifing a naming convention when creating the Rest Client. The naming convention can be any of snakeCase
, camelCase
, pascalCase
, paramCase
, or any other implemented by the change-case library.
var Users = rest.Client('http://domain.com/users/:id', { query: { convertCase: 'snakeCase' }});
Users.getAll({ page: 1, pageSize: 10 }); // Will resolve to http://domain.com/users?page=1&page_size=10
By default, arrays in the querystring will be formmated this way: ?a=1&a=2&a=2
. However, you can change it to comma separated values ?a=1,2,3
by setting the query.repeatParams
option to false
.
var client = new rest.Client(url, { query: { repeatParams: false }});
Rest-facade provides options for converting the body of the request/response. So, let's say you are consuming an API implemented in Python (using snake_case) and you want it converted to camelCase. You would specify the following options:
var client = new rest.Client(url, {
request: {
body: {
convertCase: 'snakeCase'
}
},
response: {
body: {
convertCase: 'camelCase'
}
}
});
Once that's done, you can send any request and the body of it will be converted to snake_case. E.g.
client.create({ firstName: 'John', lastName: 'Doe' });
// The server will receive
// { first_name: 'John', last_name: 'Doe' }
The same way, all the responses from the server will converted to the specified case (camelCase in this example).
Sometimes you need to do some customization to each individual request that is sent to the consumed API, a likely candidate is for adding request-specific headers.
This can be done in two ways:
options.request.customizer
_requestCustomizer
property (which should be a function as well!)You can define both, in which case both will be applied (in the order listed above).
In each case the function is passed the req
and params
representing the API call in question.
Request customizer functions may be asynchronous. If you require an asynchronous customizer function, use a callback. For example:
customizer(req, params, cb) {
someAsynchronousFunction
.then((resultOfYourFunction) => {
req.set('Authorization', `Bearer ${resultOfYourFunction}`);
return cb();
})
.catch(err => cb(err));
},
Rest-facade has superagent-proxy
as peer dependency to add proxy support. To use a proxy, you must first install the peer dependency.
npm install superagent-proxy
If a proxy URI is provided, all requests will be sent through that proxy.
// Rest client that sends all requests through a proxy server.
var client = new rest.Client(url, {
proxy: 'https://myproxy.com:1234'
});
By default, persistent connection are not enabled. To enabled it, use the option:
var client = new rest.Client(url, {
keepAlive: true
});
By default the request body type is 'json' but you can specify a custom type as follows:
var client = new rest.Client(url, {
request: {
type: 'form'
}
});
Valid values are: json and form.
FAQs
Simple abstraction for consuming REST API endpoints
The npm package rest-facade receives a total of 220,326 weekly downloads. As such, rest-facade popularity was classified as popular.
We found that rest-facade demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.