• Stars
    star
    346
  • Rank 122,430 (Top 3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 10 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

💂‍♂️ Wrap NodeJS request module to retry http requests in case of errors

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 three new options maxAttempts, retryDelay and retryStrategy. 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 ([email protected])

More Repositories

1

mailchecker

📫 Cross-language temporary (disposable/throwaway) email detection library. Covers 55 734+ fake email providers.
PHP
1,486
star
2

check-build

🎯 Check-build - Verifies that your NodeJS project follows team conventions, is well written, up to date and secure.
JavaScript
686
star
3

match-when

🐚 Pattern matching for modern JavaScript
JavaScript
528
star
4

spinners

🛎 60+ Elegant terminal spinners for Rust
Rust
462
star
5

jq.node

jq.node - like jq but WAY MORE powerful (300+ helpers 🔥 & 1.45M modules 😱)
JavaScript
418
star
6

dot-clipboard

👝 dot-clipboard monitors your clipboard and runs scripts based on its content
JavaScript
416
star
7

node-language-detect

🇫🇷 NodeJS language detection library using n-gram
JavaScript
375
star
8

gron

gron - Make JSON greppable!
JavaScript
294
star
9

forever-webui

[unmaintained] 📡 A simple web UI for efficient NodeJS processes administration
JavaScript
293
star
10

ui-predicate

Finally a Predicate/Rule Editor UI component for the Web 🚀
JavaScript
160
star
11

node-unidecode

📃 ASCII transliterations of Unicode text
JavaScript
130
star
12

import-tweets-to-mastodon

How to import tweets to mastodon (e.g. https://framapiaf.org )
JavaScript
87
star
13

spm

spm • Scala Package Manager - it's based on sbt but npm-like :trollface:
Shell
79
star
14

influxdb-cli

SQL CLI for InfluxDB
JavaScript
70
star
15

common-env

🔑 The only configuration library you will ever need
JavaScript
70
star
16

sql-convention

👌 The only SQL conventions you will ever need
57
star
17

google-spreadsheet-cli

📊 CLI for reading and writing data into Google Spreadsheet
JavaScript
52
star
18

node-truncate

🐙 Truncate text and keeps urls safe.
JavaScript
52
star
19

network-config

Network configuration for NodeJS
JavaScript
50
star
20

spotify-downloader

A proof-of-concept that transforms a Spotify playlist to a direct-download list
JavaScript
50
star
21

stripe-schema

Complete Stripe (🥰) schema (as of 2019-10-09): for learning and inspiration.
Shell
34
star
22

xobject-observe

🔬 A cross-browser object property observer using ES6 proxy with a fallback on dirty-checking.
JavaScript
33
star
23

if-exp

🎩 Conditional expressions for JavaScript
JavaScript
32
star
24

postgresql-to-amqp

PostgreSQL to AMQP, forward PostgreSQL notifications to an AMQP queue.
Rust
30
star
25

node-amqp-tool

AMQP-tool - Import & export data from/to an AMQP/RabbitMQ broker
JavaScript
26
star
26

kubectx-rs

Switch between Kubernetes contexts 🏎
Shell
25
star
27

pound

Pound - High-level asset Manager for Node.js/Express
JavaScript
25
star
28

alfred-crates

Workflow for searching Rust crates from Alfred
Rust
21
star
29

jsobjectdiff

Ensure that two JavaScript files containing objects have the same keys and display differences
JavaScript
21
star
30

node-children

Concurrent tasks computation among NodeJS child processes (vertical scaling)
JavaScript
20
star
31

npm-interactive-scripts

⚡️Fast Interactive CLI for npm scripts
JavaScript
18
star
32

stripe-update-card

💳 Expose a page that let your customers update their payment information on Stripe.
Rust
18
star
33

redis-tool

Redis-tool - Little helpers for Redis
JavaScript
17
star
34

json-schema-documentation

JSON-Schema documentor (generator, cli, themes)
JavaScript
16
star
35

Growl-Chrome-Notification

Notifications Growl pour Google Chrome :: Proof of concept :: HTML5 Web Notification API + WebSocket + NodeJS
JavaScript
16
star
36

mixpanel_export_people

Export Mixpanel people properties to an Excel Compatible CSV
JavaScript
16
star
37

node-tolerant-url-parser

Overly tolerant url parser specialized in parsing protocol, auth (even invalid ones), host and port url parts.
JavaScript
15
star
38

droplr-backup

How to backup your droplr account
JavaScript
15
star
39

stream-valve

🔐 Ensure that a stream disconnects if it goes over `maxBytes` `perSeconds`
JavaScript
14
star
40

filesync

👥 Unidirectional 1-N file syncing with history and local merging
JavaScript
14
star
41

redistree

RedisTree - load & save Trees to Redis using sets
JavaScript
13
star
42

request-api

NodeJS request library as HTTP API
JavaScript
13
star
43

node-redis-info

Redis info string parser for NodeJS
JavaScript
13
star
44

this-is-your-life

This if your life
JavaScript
12
star
45

rss-to-amp-stories

RSS to AMP Stories ⚡️
HTML
12
star
46

latenize

NPM/NodeJS port of Semplice latenize
JavaScript
12
star
47

amqp-replay

📹 Replay messages from (RabbitMQ) AMQP dead-letter queue
JavaScript
12
star
48

smtp-to-sendgrid-gateway

Forward emails from SMTP requests to the Sendgrid API. Useful when the cloud provider does not allow outbound connections on ports 25, 465, 587.
JavaScript
11
star
49

my-first-nodejs-service

🐾 Workshop my first nodejs service
JavaScript
11
star
50

node-transacemail

Transactional Email & Templated Email for NodeJS done right
JavaScript
11
star
51

stargazerz

Stargazerz - export repository 🌟 stargazers 🌟 profile as JSON
JavaScript
9
star
52

kubectx

Fastest switch between #Kubernetes contexts 🏎
JavaScript
9
star
53

mixpanel-cli

🎩 mixpanel-cli - A complete CLI to query Mixpanel API
JavaScript
9
star
54

stripe-integration

Easiest Stripe Integration (ever)
Rust
9
star
55

rss-to-lametric

Your favorite RSS feed directly from your LaMetric 🎩
Rust
8
star
56

tumblr-analysis

Extract every tumblr posts as JSON from a blog and analyze them.
JavaScript
8
star
57

node-amqp-dsl

AMQP-DSL is a fluent interface for AMQP (RabbitMQ,...) on NodeJS
CoffeeScript
8
star
58

123PeopleRemover-proxy

Proxy pour 123PeoplerRemover à installer sur votre serveur
PHP
8
star
59

jQuery-plugin-attributeObserver

jQuery plugin for observing html element's property changes
JavaScript
8
star
60

node-nice-console

Patch NodeJS console methods in order to add timestamp information
JavaScript
8
star
61

gcloud

Google Cloud API client for Rust
Rust
8
star
62

jQuery-plugin-fireEvent

jQuery FireEvent - Plugin for firing real DOM events
JavaScript
8
star
63

jQuery-plugin-getPath

jQuert getPath - Find a (possible) jQuery selector of an HTML element.
JavaScript
7
star
64

node-ast-inlining

Node Ast Inlining is a small (~200 LOC) library that inline and expand function call
JavaScript
7
star
65

preg_replace---preg_replace_callback-in-javascript

PHP functions preg_replace & preg_replace_callback javascript equivalent
JavaScript
7
star
66

node-x509-certificate

Retrieve the public TLS certificate in x509 format from a distant host
JavaScript
7
star
67

lool

:trollface: Infinitely recursive self-installing useless package.
6
star
68

querystring

🦄 Querystring for Rust
Rust
5
star
69

twitterremover

How I "hijacked" Topsy private search api to remove my first 5000+ tweets
JavaScript
5
star
70

scaleway-api-client

☁ Scaleway NodeJS API Client 🚀
JavaScript
5
star
71

self-worth

See jeffreybaird/self-worth
Ruby
5
star
72

jscs2doc

🎊 Convert .jscsrc (javascript code-style configuration) to a human readable format
JavaScript
5
star
73

rk

Original idea by @stockholmux in Dancing around strings in Node.js and Redis
JavaScript
5
star
74

json-combine

Generate every possible combination of values
JavaScript
4
star
75

chrome-freeze-tab-title

Freeze Tab Title & Favicon Chrome Extension - Increase productivity & Reduce procrastination 🌟🌟
JavaScript
4
star
76

backbone-cappedcollection

Capped Collections for BackboneJS
JavaScript
4
star
77

Trickle-clone

A Quick & Dirty trickle clone
JavaScript
4
star
78

valid-json-template

Use a (valid) JSON as a template that produce another valid JSON as a result
JavaScript
4
star
79

terraform-workspace-switcher

Fastest switch between Terraform workspaces
Shell
4
star
80

clipboard-watcher

Listen to clipboard change (OSX only)
JavaScript
4
star
81

bmw_oss_dvd

♣️ BMW Open Source Software (OSS) DVD - I received for my BMW X3
3
star
82

big-brother

Web2Day Hackathon 2011
JavaScript
3
star
83

JSCSSP

JSCSSP without DOM pollution
JavaScript
3
star
84

app-demonstrator

Proof of Concept - (iPhone & co) Application demonstrator
JavaScript
3
star
85

postgrest-patch-request-trigger

How PostgreSQL triggers works when called with a PostgREST PATCH HTTP request
PLpgSQL
3
star
86

hostname-is-private

:squirrel: Check whether or not an hostname refers to a private IP
JavaScript
3
star
87

join-events

▶️ Join events stream compatible with event emitter
JavaScript
3
star
88

url-is-private

Check whether or not an url refer to a private IP
JavaScript
3
star
89

maintainers-convention

💂‍♂️ Ensure a MAINTAINERS file exist inside every repository of a Github Organisation
JavaScript
3
star
90

node-asynccallguard

Make all calls to a function queued and asynchronously guarded
JavaScript
3
star
91

ai-rom

TP cours d'IA
C
2
star
92

cancelable

Cancelable JavaScript functions
JavaScript
2
star
93

request-when

Request + WhenJS
JavaScript
2
star
94

ai-GeneticAlgorithm

Genetical Algorithm w/ Chessboard
C
2
star
95

elasticsearch-exceptions

Parse Elasticsearch exception responses and transform them into JavaScript Errors
JavaScript
2
star
96

Kuripotxt

A simple PHP Class for sending sms using Kuripotxt
2
star
97

stretchtext

StretchText
JavaScript
2
star
98

iPhone-Particles

Simple iPhone Particles App
JavaScript
2
star
99

docker-jenkins-slave

💪 Run a Jenkins slave in docker AND access to docker cli from jobs
2
star
100

node-transacemail-mandrill

Mandrill mailProvider for node-transacemail
JavaScript
2
star