Détail du package

requestretry

FGRibreau960.3kMIT7.1.0

request-retry wrap nodejs request to retry http(s) requests in case of error

readme


request-retry - HTTP(s) request retry on recoverable errors.


Coverage Status NPM version Downloads

Get help on Codementor available-for-advisory extra Slack

When the connection fails with one of ECONNRESET, ENOTFOUND, ESOCKETTIMEDOUT, ETIMEDOUT, ECONNREFUSED, EHOSTUNREACH, EPIPE, EAI_AGAIN or when an HTTP 5xx or 429 error occurrs, the request will automatically be re-attempted as these are often recoverable errors and will go away on retry.

❤️ Shameless plug

Installation

Install with npm.

npm install --save requestretry

Usage

Request-retry is a drop-in replacement for request but adds two new options maxAttempts and retryDelay. It also adds one property to the response (or the error object, upon a network error), attempts. It supports callbacks or promises.

With callbacks

var request = require('requestretry');

request({
  url: 'https://api.domain.com/v1/a/b',
  json: true,

  // The below parameters are specific to request-retry
  maxAttempts: 5,   // (default) try 5 times
  retryDelay: 5000,  // (default) wait for 5s before trying again
  retryStrategy: request.RetryStrategies.HTTPOrNetworkError // (default) retry on 5xx or network errors
}, function(err, response, body){
  // this callback will only be called when the request succeeded or after maxAttempts or on error
  if (response) {
    console.log('The number of request attempts: ' + response.attempts);
  }
});

With promises

When you're using promises, you can pass the two following options:

  • fullResponse (default true) - To resolve the promise with the full response or just the body
  • promiseFactory (default whenjs) - A function to allow the usage of a different promise implementation library
request({
  url: 'https://api.domain.com/v1/a/b',
  json: true,

  fullResponse: true // (default) To resolve the promise with the full response or just the body
})
.then(function (response) {
  // response = The full response object or just the body
})
.catch(function(error) {
  // error = Any occurred error
})

Using promiseFactory option to use a different promise implementation library

// See the tests for different libraries usage examples

/**
 * @param  {Function} resolver The promise resolver function
 * @return {Object} The promise instance
 */
function customPromiseFactory(resolver) {
  // With when.js
  return require('when').promise(resolver);

  // With RSVP.js
  var Promise = require('rsvp').Promise;

  return new Promise(resolver);
}

request({
  url: 'https://api.domain.com/v1/a/b',
  json: true,

  // Custom promise factory function
  promiseFactory: customPromiseFactory
})
.then(function (response) {
  // response = The full response object or just the body
})
.catch(function(error) {
  // error = Any occurred error
})

How to define your own retry strategy

A retry strategy let you specify when request-retry should retry a request

/**
 * @param  {Null | Object} err
 * @param  {Object} response
 * @param  {Object} body
 * @param  {Object} options copy 
 * @return {Boolean} true if the request should be retried
 */
function myRetryStrategy(err, response, body, options){
  // retry the request if we had an error or if the response was a 'Bad Gateway'
  return !!err || response.statusCode === 502;
}

/**
 * @param  {Null | Object} err
 * @param  {Object} response
 * @param  {Object} body
 * @param  {Object} options copy 
 * @return {Object} mustRetry: {Boolean} true if the request should be retried
 *                  options: {Object} new options for request
 */
function myRetryStrategy(err, response, body, options){
  options.url = 'new url'; //you can overwrite some attributes or create new object 
  return {
    mustRetry: !!err || response.statusCode === 502,
    options: options, //then it should be passed back, it will be used for new requests
  }
}

/**
 * With an asynchronous retry strategy
 * @param  {Null | Object} err
 * @param  {Object} response
 * @param  {Object} body
 * @param  {Object} options copy 
 * @return {Object} mustRetry: {Boolean} true if the request should be retried
 *                  options: {Object} new options for request
 */
async function myRetryStrategy(err, response, body, options){
  let token = await getNewApiAuthToken();
  options.headers = {'Authorization': `Bearer ${token}`}
  return {
    mustRetry: true,
    options: options, // retry with new auth token
  }
}

request({
  url: 'https://api.domain.com/v1/a/b'
  json:true,
  retryStrategy: myRetryStrategy
}, function(err, response, body){
  // this callback will only be called when the request succeeded or after maxAttempts or on error
});

How to define your own delay strategy

A delay strategy let you specify how long request-retry should wait before trying again the request

/**
 * @param  {Null | Object} err
 * @param  {Object} response
 * @param  {Object} body
 * @return {Number} number of milliseconds to wait before trying again the request
 */
function myDelayStrategy(err, response, body){
  // set delay of retry to a random number between 500 and 3500 ms
  return Math.floor(Math.random() * (3500 - 500 + 1) + 500);
}

request({
  url: 'https://api.domain.com/v1/a/b'
  json:true,
  delayStrategy: myDelayStrategy // delayStrategy is called 1 less times than the maxAttempts set
}, function(err, response, body){
  // this callback will only be called when the request succeeded or after maxAttempts or on error
});

Here is how to implement an exponential backoff strategy:

/**
 * @param   {Number} attempts The number of times that the request has been attempted.
 * @return  {Number} number of milliseconds to wait before retrying again the request.
 */
function getExponentialBackoff(attempts) {
  return (Math.pow(2, attempts) * 100) + Math.floor(Math.random() * 50);
}

function constructExponentialBackoffStrategy() {
  let attempts = 0;
  return () => {
    attempts += 1;
    return getExponentialBackoff(attempts);
  };
}

request({
  url: 'https://api.domain.com/v1/a/b'
  json:true,
  delayStrategy: constructExponentialBackoffStrategy() // need to invoke the function to return the closure.
}, function(err, response, body){
  // this callback will only be called when the request succeeded or after maxAttempts or on error
});

How to access the underlying request library

You can access to the underlying request library thanks to request.Request:

const request = require('requestretry');
console.log(request.Request); // original request library

Thus, if needed, it's possible to monkey-patch or extend the underlying Request library:

request.Request = class extends request.Request {
  constructor(url, options, f, retryConfig) {
    super(url, options, f, retryConfig);
    // this constructor will be called for every requestretry call,
    // and give you global logging
    console.log('Request', url, options, f, retryConfig);
  }
}

Modifying request options

You can use the defaults method to provide default options like so:

var request = require('requestretry').defaults({ json: true, retryStrategy: myRetryStrategy });

API surface

As with request, several helpers are provided for various HTTP methods and usage:

  • request(options [, callback]).
  • request(url [, callback]) - same as request(options [, callback]).
  • request(url, options [, callback]) - same as request(options [, callback]).
  • request.get(url [, callback]) - same as request(options [, callback]), defaults options.method to GET.
  • request.get(url, options [, callback]) - same as request(options [, callback]), defaults options.method to GET.
  • request.head(url) - same as request(options [, callback]), defaults options.method to HEAD.
  • request.post(url) - same as request(options [, callback]), defaults options.method to POST.
  • request.put(url) - same as request(options [, callback]), defaults options.method to PUT.
  • request.patch(url) - same as request(options [, callback]), defaults options.method to PATCH.
  • request.del(url) - same as request(options [, callback]), defaults options.method to DELETE.
  • request.delete(url) - same as request(options [, callback]), defaults options.method to DELETE.

Changelog

You want to support my work?

I maintain this project in my free time, if it helped you, well, I would be grateful to buy a beer thanks to your paypal or Bitcoins, donation!

Francois-Guillaume Ribreau (npm@fgribreau.com)

changelog

7.1.0 (2022-04-12)

  • add skipHeaderSanitize option (a608d09)
  • add skipHeaderSanitize test (08e181a)
  • Release v7.1.0. (3be9409)
  • docs(changelog): updated (e1c577b)

7.0.2 (2022-03-04)

  • better syntax (56e04b7)
  • fixed bug when receiving array parameter (89945eb)
  • Release v7.0.2. (4e3fa9d)
  • fix: do not publish to npm useless files (93ae32b)
  • docs(changelog): updated (b22adc5)

7.0.1 (2022-03-03)

7.0.0 (2022-02-21)

  • changes (2d822ad)
  • Prevent Cookie & Authorization Headers from being forwarded when the URL redirects to another domain (0979c60), closes #137
  • Release v7.0.0. (4569005)
  • Update leak.test.js (2768f5c)
  • Update leak.test.js (afa27ef)
  • Update README.md (5e1a63c)
  • Update README.md (ebf3471)
  • test: add more test (c7c47d6)
  • fix: :facepalm: (3c0d686)
  • fix: breaking test suite (95e7a3b)
  • docs(changelog): updated (a450999)

6.0.0 (2021-08-24)

  • Release v6.0.0. (1b8ea5c)
  • fix: remove dependency on when in favor of native Promises (52d0603)
  • docs(changelog): updated (a1189ef)

5.0.0 (2021-02-16)

4.1.2 (2020-11-11)

4.1.1 (2020-05-18)

4.1.0 (2020-01-10)

4.0.2 (2019-10-12)

  • Release v4.0.2. (a73a0ee)
  • fix(package): do not expose coverage & .nyc_output (7d7ed22)
  • docs(changelog): updated (d3d9881)

4.0.1 (2019-10-12)

4.0.0 (2019-03-14)

  • Ensure mustRetry object has mustRetry property in retryStrategy return value (9a3dedf)
  • Release v4.0.0. (0b3fab7)
  • docs(changelog): updated (94e086e)

3.1.0 (2018-11-28)

  • Changed return type of retryStrategy to [mustRetry, options], overwrite options if strategy retu (3080eb7)
  • Release v3.1.0. (c05651b)
  • RetryStrategy can return Bool or Object, changes are backward compatible. (ac78e14)
  • Updated Readme (731c712)
  • fix: upgrade devDeps (77dd58b)
  • docs(changelog): updated (52e45de)

3.0.2 (2018-10-23)

3.0.1 (2018-09-26)

3.0.0 (2018-09-21)

  • Also retry on HTTP Status 429 "Too Many Requests" (bf447d7)
  • Release v3.0.0. (9a16328)
  • docs(changelog): updated (65e5a68)

2.0.2 (2018-08-01)

2.0.1 (2018-08-01)

2.0.0 (2018-07-17)

  • BREAKING CHANGE: moving request dependency as a peerDependency. If you don't have request already (128030e)
  • make request a peer dependency (aafafe3)
  • Release v2.0.0. (e3f05f5)
  • docs(changelog): updated (54a604a)

1.13.0 (2018-01-18)

1.12.3 (2018-01-18)

  • Added testing for error object attempts reporting (578870f)
  • Added the attempts property and assigned it to the error object returned when a network error occurs (ecd9f5c)
  • Adds exponential backoff example to readme. (184b84f)
  • Release v1.12.3. (57bb3d8)
  • Typo in Readme for Exponential Backoff Delay. (b9ef000)
  • Update attempts.test.js (32a699d)
  • Update README.md (9d1367b)
  • Update README.md (eed7f88)
  • chore(git): remove package-lock.json from gitignore (08631fa)
  • docs(changelog): updated (cbe2355)

1.12.2 (2017-08-01)

  • Added .auth, .jar and .cookie implementations along with corresponding tests (15afe79)
  • formatting updated + version bump (6ad6f09)
  • Improve README. (5052add)
  • minor fix (5b3f6d1)
  • Release v1.12.1. (a1d198a)
  • Release v1.12.2. (eba306c)
  • revert (d6a840f)
  • split various.test.js in auth.test.js and cookie.test.js (c80272b)
  • Update package.json (9619999)
  • Update README.md (9a50640)
  • Update README.md (ada51e3)
  • Update README.md (984fd17)
  • Update README.md (94b8c01)
  • chore(package): update dependencies (85c62ac)
  • chore(package): update nyc to version 10.0.0 (f652825)
  • chore(package): update nyc to version 9.0.1 (e376616)
  • chore(package): update sinon to version 1.17.6 (2735e7c)
  • docs(changelog): updated (448b9e1)

1.12.0 (2016-09-07)

1.11.0 (2016-09-03)

  • fix(circle) (e6c2160)
  • fix(deps) (35921bb)
  • Release v1.11.0. (560e402)
  • Update README.md (85b63ad)
  • fix(tests): bring node-request-retry to a 100% code-coverage (6275780)
  • feat(api): larger api-surface, just like request (1527f9d)

1.10.0 (2016-08-18)

1.9.1 (2016-07-29)

1.9.0 (2016-06-22)

  • Add support for body-dependent retry strategies (0f472f9)
  • Amended for body-dependent retry strategies (db7a4ef)
  • Release v1.9.0. (5bdee74)
  • docs(changelog): updated (ca04ea7)

1.8.0 (2016-05-11)

1.7.1 (2016-05-11)

1.7.0 (2016-05-06)

1.6.0 (2015-12-25)

  • Added bluebird and nock dependencies (2062358)
  • Added tests for promiseFactory option, using (when.js, Q, kew, RSVP.js) promises libraries (2cd5c6a)
  • docs(changelog) (55efd7d)
  • docs(readme) (d291e9b)
  • docs(readme) (41e893b)
  • fix(index) (51d087c)
  • Fixed typo (f24205d)
  • Implemented promiseFactory option, to allow usage of different promise libraries (7a5e11c)
  • Implemented promises support (27484f0)
  • Implemented tests for promises (609d820)
  • Minor example text fix (2edefc4)
  • Release v1.6.0. (99118dd)
  • Removed test suite exclusive only modifier (71ec0d2)
  • Updated README for usage with promises (d66a77a)
  • feat(promise): using when.js by default instead of bluebird (f9dddf9)

1.5.0 (2015-09-24)

  • Actually add attempts test (0db5402)
  • Add the attempts property for retry attempt info. Add a test for it. Also fix maxAttempts being of (a130355)
  • feat(changelog) (bf0ff38)
  • Release v1.5.0. (1b7ca7c)
  • fix(dot-files): .env to ignored files (145a33e)

1.4.1 (2015-09-21)

1.4.0 (2015-07-16)

  • add EAI_AGAIN to the list of retriable network errors (64b96ff)
  • add notes on request module to readme (e7acf85)
  • Release v1.4.0. (e890593)
  • feat(deps): upgrade request to 2.58.x (e7d34a1)

1.3.1 (2015-05-06)

  • Release v1.3.1. (bef5dba)
  • docs(changelog): add changelog (5ea057b)
  • feat(check-build): add check-build (13c4029)

1.3.0 (2015-05-06)

  • Release v1.3.0. (07ac122)
  • update dependencies for latest version (30da1b0)

1.2.2 (2015-01-03)

1.2.1 (2014-11-10)

1.2.0 (2014-11-03)

1.1.0 (2014-10-27)

  • add @juliendangers as contributor (27206d8)
  • apply original format (04fa9c6)
  • expose methods from internal Request (end, on, emit, once, setMaxListeners, start, removeListener, p (7d2a0b5)
  • jsformat (581179a)
  • Release v1.1.0. (6708bb0)
  • setting the prototype inside the constructor, will do this at each instanciation. We don't need the (ea0f474)
  • update deps (f62935c)
  • update readme (849b78b)

1.0.4 (2014-09-30)

1.0.3 (2014-09-23)