|![retry-request](logo.png) |:-: |Retry a [request][request] with built-in [exponential backoff](https://developers.google.com/analytics/devguides/reporting/core/v3/coreErrors#backoff). ```sh $ npm install --save request $ npm install --save retry-request ``` ```js var request = require('retry-request', { request: require('request') }); ``` It should work the same as `request` in both callback mode and stream mode. Note: This module only works when used as a readable stream, i.e. POST requests aren't supported ([#3](https://github.com/stephenplusplus/retry-request/issues/3)). ## Do I need to install `request`? Yes! You must independently install `request` and provide it to this library: ```js var request = require('retry-request', { request: require('request') }); ``` *The code will actually look for the `request` module automatically to save you this step. But, being explicit like in the example is also welcome.* #### Callback `urlThatReturns503` will be requested 3 total times before giving up and executing the callback. ```js request(urlThatReturns503, function (err, resp, body) {}); ``` #### Stream `urlThatReturns503` will be requested 3 total times before giving up and emitting the `response` and `complete` event as usual. ```js request(urlThatReturns503) .on('error', function () {}) .on('response', function () {}) .on('complete', function () {}); ``` ## Can I monitor what retry-request is doing internally? Yes! This project uses [debug](https://www.npmjs.com/package/debug) to provide the current retry attempt, each response status, and the delay computed until the next retry attempt is made. To enable the debug mode, set the environment variable `DEBUG` to *retry-request*. (Thanks for the implementation, @yihaozhadan!) ## request(requestOptions, [opts], [cb]) ### requestOptions Passed directly to `request`. See the list of options supported: https://github.com/request/request/#requestoptions-callback. ### opts *(optional)* #### `opts.noResponseRetries` Type: `Number` Default: `2` The number of times to retry after a response fails to come through, such as a DNS resolution error or a socket hangup. ```js var opts = { noResponseRetries: 0 }; request(url, opts, function (err, resp, body) { // url was requested 1 time before giving up and // executing this callback. }); ``` #### `opts.objectMode` Type: `Boolean` Default: `false` Set to `true` if your custom `opts.request` function returns a stream in object mode. #### `opts.retries` Type: `Number` Default: `2` ```js var opts = { retries: 4 }; request(urlThatReturns503, opts, function (err, resp, body) { // urlThatReturns503 was requested a total of 5 times // before giving up and executing this callback. }); ``` #### `opts.currentRetryAttempt` Type: `Number` Default: `0` ```js var opts = { currentRetryAttempt: 1 }; request(urlThatReturns503, opts, function (err, resp, body) { // urlThatReturns503 was requested as if it already failed once. }); ``` #### `opts.shouldRetryFn` Type: `Function` Default: Returns `true` if [http.incomingMessage](https://nodejs.org/api/http.html#http_http_incomingmessage).statusCode is < 200 or >= 400. ```js var opts = { shouldRetryFn: function (incomingHttpMessage) { return incomingHttpMessage.statusMessage !== 'OK'; } }; request(urlThatReturnsNonOKStatusMessage, opts, function (err, resp, body) { // urlThatReturnsNonOKStatusMessage was requested a // total of 3 times, each time using `opts.shouldRetryFn` // to decide if it should continue before giving up and // executing this callback. }); ``` #### `opts.request` Type: `Function` Default: `try { require('request') }` If we cannot locate `request`, we will throw an error advising you to provide it explicitly. *NOTE: If you override the request function, and it returns a stream in object mode, be sure to set `opts.objectMode` to `true`.* ```js var originalRequest = require('request').defaults({ pool: { maxSockets: Infinity } }); var opts = { request: originalRequest }; request(urlThatReturns503, opts, function (err, resp, body) { // Your provided `originalRequest` instance was used. }); ``` ### cb *(optional)* Passed directly to `request`. See the callback section: https://github.com/request/request/#requestoptions-callback. [request]: https://github.com/request/request