|![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
