WARNING: DEPRECATED PACKAGE
I've made a mistake while naming this package, so I decided to create a new one with a different name and lightly different goal, using TypeScript.
Have a look at @jalik/fetch-client to use an HTTP client based on fetch which runs in the Browser and NodeJS, with global config, shortcut methods, transformations capabilities and more.
We often repeat our self when creating a REST client, however there are some little things that could be avoided on each request, like concatenating base URL with path, passing credentials, serializing data...
With this lib, you can build a REST client quickly and almost effortlessly. It can also be used to create an REST SDK, so your users would not have to craft the requests entirely.
Let's see how to create a REST client.
import RestClient from '@jalik/rest-client';
const client = new RestClient({
// The base URL of all requests.
baseUrl: 'https://rest.coinapi.io/v1',
});
Fetch is the standard and simplest way to execute HTTP requests in web browsers using Promise
.
This lib is using fetch()
under the hood (via the whatwg-fetch
polyfill package), so if you know how to use fetch()
, you already know how to craft requests with this REST client.
See how to use fetch on https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch.
const body = { name: 'Karl' };
client.fetch('/users', {
method: 'POST',
body: JSON.stringify(body),
headers: {
'content-type': 'application/json'
}
})
.then((resp) => {
// handle response
})
.catch((error) => {
// handle error
});
This method is generic, so to make code more concise and readable, you can use any of the next shortcut methods, which correspond to an HTTP verb.
Note about JSON serialization
The fetch()
method which is called by all the methods below (delete, get, patch...) will automatically serialize the request body, if body
is an object and the header content-type
is application/json
.
client.delete('/users/1')
.then((resp) => {
// handle response
})
.catch((error) => {
// handle error
});
client.get('/users', {
headers: { accept: 'application/json' }
})
.then((resp) => resp.json())
.then((json) => {
// handle response
})
.catch((error) => {
// handle error
});
client.head('/users', {
headers: { accept: 'application/json' }
})
.then((resp) => {
// handle response
})
.catch((error) => {
// handle error
});
client.options('/users', {
headers: { accept: 'application/json' }
})
.then((resp) => {
// handle response
})
.catch((error) => {
// handle error
});
const body = { name: 'Karl' };
client.patch('/users/1', body, {
headers: { 'content-type': 'application/json' }
})
.then((resp) => {
// handle response
})
.catch((error) => {
// handle error
});
const body = { name: 'Karl' };
client.post('/users', body, {
headers: { 'content-type': 'application/json' }
})
.then((resp) => {
// handle response
})
.catch((error) => {
// handle error
});
const body = { name: 'Karl' };
client.put('/users', body, {
headers: { 'content-type': 'application/json' }
})
.then((resp) => {
// handle response
})
.catch((error) => {
// handle error
});
Headers can be set when creating the RestClient
instance.
For example the code below will send the accept
header with all requests (while being overridable on each request).
const client = new RestClient({
baseUrl: 'https://rest.coinapi.io/v1',
headers: {
accept: 'application/json',
}
});
Headers can be get or set at anytime and anywhere in your code.
client.setHeader('accept', '*');
client.getHeader('accept');
Note that all header names are lower cased automatically in getHeader()
and setHeader()
to make it more bug proof, so the following code is referring to the same header.
// Define 'accept' header equivalents
client.setHeader('Accept', '*');
client.setHeader('ACCEPT', '*');
client.setHeader('accept', '*');
// Return 'accept' header equivalents
client.getHeader('Accept');
client.getHeader('ACCEPT');
client.getHeader('accept');
If you need to override or remove specific headers for a request it's still possible by passing these headers in the request options. The next example works with all methods (delete, patch, post...).
// This will replace the `accept` header only for this request.
client.get('/users', {
headers: { accept: 'application/xml' }
});
// This will not send current credentials for this request.
client.post('/auth', { user: 'jalik', pass: 'yun8amginIr#' }, {
headers: { authorization: '' }
});
Finally, if you need to loop through all defined headers.
client.getHeaderNames().forEach((name) => {
const value = client.getHeader(name);
// do something with value...
});
Generally, authenticating against an API is done by providing a header, which could be the classic authorization
header or a custom access token header. Below is a list of examples showing some of them.
// Basic authentication
client.setHeader('authorization', 'Basic dGVzdDoxMjPCow==');
// Bearer authentication
client.setHeader('authorization', 'Bearer mF_9.B5f-4.1JqM');
// Custom access token (api key)
client.setHeader('x-api-key', 'Jec5omtyacuzUcCanQuibPyFrajecEif');
Note that there is no mechanism to support token as query parameter because it is a bad practice and not secure (https://tools.ietf.org/html/rfc6750#section-2.3). However, this can still be achieved by passing the access token on each request manually.
History of releases is in the changelog.
The code is released under the MIT License.