Promises/A+, request-powered, boom-enabled, JSON-first HTTP API client with automatic retry
Install with npm
:
npm install habrok --save
const Habrok = require('habrok');
const habrok = new Habrok();
habrok.request({
method: 'GET',
uri: 'https://api.github.com/repositories'
})
.then(console.log);
{
"statusCode": 200,
"headers": {
"content-length": "4477",
"content-type": "application/json; charset=utf-8",
"etag": "6ffc6a0dbbe2613e4d8b3f7444e5c604",
...
},
"body": [
{
"id": 1296269,
"private": false,
"owner": {
"id": 1,
"login": "octocat",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
...
},
"name": "hello-World",
"full_name": "octocat/hello-world",
"description": "Octocat's first repo!",
"url": "https://api.github.com/repos/octocat/hello-world",
...
},
...
]
}
Habrok([configuration])
None
configuration
:Object
with one or more of the below properties:
Property | Type | Description | Default |
---|---|---|---|
disableAutomaticJson |
Boolean |
Disable JSON headers and request/response bodies | false |
disableCustomHeaders |
Boolean |
Disable request headers added by Habrok | false |
disableRetryEconnreset |
Boolean |
Disable retry for connection reset errors | false |
retries |
Number |
Number of times to retry a failed request | 5 |
retryMinDelay |
Number |
Minimum milliseconds to wait before retrying a request | 100 |
retryMaxDelay |
Number |
Maximum milliseconds to wait before retrying a request | None |
retryCodes |
Array<Number> |
HTTP status codes that trigger a retry | [429, 502, 503, 504] |
By default, each request includes the following headers (which can be prevented with disableCustomHeaders
):
User-Agent
:habrok/[MAJOR.MINOR.PATCH]
, versioned according topackage.json
(e.g.habrok/1.0.0
)X-Node-Platform
: Directly fromprocess.platform
(e.g.linux
)X-Node-Version
: Derived fromprocess.version
(e.g.6.11.1
)
The retry logic follows exponential backoff, summarized as:
MINIMUM(retryMaxDelay, retryMinDelay * (attempt ** 2))
With the default configuration
, a failing request observes a delay sequence of 100
, 400
, 900
, and 1600
milliseconds before rejecting with an error.
A Habrok HTTP API Client instance.
Construct a default client:
const Habrok = require('habrok');
const habrok = new Habrok();
Construct a client with a minimum retry delay of 250 milliseconds:
const Habrok = require('habrok');
const habrok = new Habrok({ retryMinDelay: 250 });
Construct a client that does not send Habrok-generated headers:
const Habrok = require('habrok');
const habrok = new Habrok({ disableCustomHeaders: true });
habrok.request(req[, options])
req
:Object
, a request-compatible object
options
:Object
with one or more of the below properties:
Property | Type | Description | Default |
---|---|---|---|
attempt |
Number |
Integer indicating current request sequence number | None |
onRetry |
Function |
A function executed whenever Habrok retries a request. As an argument, it will pass in an object with same properties returned by a habrok.request . |
None |
debugRequest |
Function |
A function called after making a successful request or after the maximum number of attempts is met. As an argument, it will pass in an object with the property attempt , the number of attempts made. |
None |
Generally, attempt
is not needed. The internal retry engine will pass the current attempt count into the next request. Override only as necessary – e.g. in cases where the retry logic should be bypassed.
Parameters
Parameter | Type | Description |
---|---|---|
statusCode | Number |
The HTTP status code of the request that necessitated this retry. |
error | Object |
A boom-js error. |
Returns None
Parameters
Parameter | Type | Description |
---|---|---|
debugInfo | Object |
An object containing information about the series of requests. |
debugInfo
Key | Type | Description |
---|---|---|
attempts |
Number |
The total number of http requests made for a habrok.request . If retries is set to 0, and this will always be 1. |
Returns None
A Promise
that resolves to an Object
with the following properties:
statusCode
:Number
, the HTTP status code provided in the responseheaders
:Object
, HTTP headers (lower-cased) and their values provided in the responsebody
:Any
, the JSON-parsed response body (or the raw body ifdisableAutomaticJson
was set)
The Promise
is rejected with a Boom-wrapped error if an HTTP error occurs. The Promise
is rejected with a generic Error
if an error is returned by the underlying request library (usually from http.ClientRequest).
Send a GET
request:
habrok.request({
method: 'GET',
uri: 'https://api.viki.ng/longships'
})
Send a POST
request:
habrok.request({
method: 'POST',
uri: 'https://api.viki.ng/longships',
json: {
name: 'Oseberg'
}
})
The debug module is used for runtime logging. Omit the DEBUG
environment variable to squelch all logging. Set DEBUG
to the desired level (e.g. DEBUG=habrok
) to restrict logging to a desired service. Or, use DEBUG=*
to get all debug output from everywhere, including dependencies.
DEBUG=@agilemd/habrok* node index
To run the unit tests:
npm test
This project maintains ~100% coverage of statements, branches, and functions. To determine unit test coverage:
npm run coverage
PRs are welcome! PRs must pass unit tests and linting prior to merge. PRs must not reduce unit coverage. For bugs, please include a failing test which passes when your PR is applied. To enable a git hook that runs npm test
prior to pushing, cd
into your repo and run:
touch .git/hooks/pre-push
chmod +x .git/hooks/pre-push
echo "npm test" > .git/hooks/pre-push
This project follows semantic versioning. See the changelog for release information.
- This module is licensed under the ISC License
- The underlying
boom
module is licensed under the BSD 3-Clause License - The underlying
debug
module is licensed under the MIT License - The underlying
has
module is licensed under the MIT License - The underlying
request
module is licensed under the Apache 2.0
From Grímnismál, Stanza 44:
The best of trees must Yggdrasil be, Skithblathnir best of boats; Of all the gods is Odin the greatest, And Sleipnir the best of steeds; Bifrost of bridges, Bragi of skalds, Habrok of hawks, and Garm of hounds.
Habrok, data-in-flight at its best.