Skip to content

Commit 9f3a099

Browse files
szmarczaksindresorhus
authored andcommittedDec 10, 2018
Add ability to specify which network error codes to retry on (#660)
Fixes #654
1 parent 33b838f commit 9f3a099

6 files changed

+63
-25
lines changed
 

‎advanced-creation.md

+10
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ const defaults = {
8282
502,
8383
503,
8484
504
85+
],
86+
errorCodes: [
87+
'ETIMEDOUT',
88+
'ECONNRESET',
89+
'EADDRINUSE',
90+
'ECONNREFUSED',
91+
'EPIPE',
92+
'ENOTFOUND',
93+
'ENETUNREACH',
94+
'EAI_AGAIN'
8595
]
8696
},
8797
headers: {

‎readme.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,9 @@ Default:
259259
- methods: `GET` `PUT` `HEAD` `DELETE` `OPTIONS` `TRACE`
260260
- statusCodes: [`408`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) [`413`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/413) [`429`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) [`500`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) [`502`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502) [`503`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503) [`504`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504)
261261
- maxRetryAfter: `undefined`
262+
- errorCodes: `ETIMEDOUT` `ECONNRESET` `EADDRINUSE` `ECONNREFUSED` `EPIPE` `ENOTFOUND` `ENETUNREACH` `EAI_AGAIN`
262263

263-
An object representing `retries`, `methods`, `statusCodes` and `maxRetryAfter` fields for the time until retry, allowed methods, allowed status codes and maximum [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time.
264+
An object representing `retries`, `methods`, `statusCodes`, `maxRetryAfter` and `errorCodes` fields for the time until retry, allowed methods, allowed status codes, maximum [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time and allowed error codes.
264265

265266
If `maxRetryAfter` is set to `undefined`, it will use `options.timeout`.<br>
266267
If [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header is greater than `maxRetryAfter`, it will cancel the request.
@@ -269,7 +270,7 @@ Delays between retries counts with function `1000 * Math.pow(2, retry) + Math.ra
269270

270271
The `retries` property can be a `number` or a `function` with `retry` and `error` arguments. The function must return a delay in milliseconds (`0` return value cancels retry).
271272

272-
**Note:** It retries only on the specified methods, status codes, and on these network errors:
273+
**Note:** By default, it retries *only* on the specified methods, status codes, and on these network errors:
273274
- `ETIMEDOUT`: One of the [timeout](#timeout) limits were reached.
274275
- `ECONNRESET`: Connection was forcibly closed by a peer.
275276
- `EADDRINUSE`: Could not bind to any free port.

‎source/index.js

+10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ const defaults = {
2222
502,
2323
503,
2424
504
25+
],
26+
errorCodes: [
27+
'ETIMEDOUT',
28+
'ECONNRESET',
29+
'EADDRINUSE',
30+
'ECONNREFUSED',
31+
'EPIPE',
32+
'ENOTFOUND',
33+
'ENETUNREACH',
34+
'EAI_AGAIN'
2535
]
2636
},
2737
headers: {

‎source/normalize-arguments.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ const urlLib = require('url');
44
const is = require('@sindresorhus/is');
55
const urlParseLax = require('url-parse-lax');
66
const lowercaseKeys = require('lowercase-keys');
7-
const isRetryOnNetworkErrorAllowed = require('./utils/is-retry-on-network-error-allowed');
87
const urlToOptions = require('./utils/url-to-options');
98
const isFormData = require('./utils/is-form-data');
109
const merge = require('./merge');
@@ -56,7 +55,8 @@ const preNormalize = (options, defaults) => {
5655
options.retry = {
5756
retries: 0,
5857
methods: [],
59-
statusCodes: []
58+
statusCodes: [],
59+
errorCodes: []
6060
};
6161

6262
if (is.nonEmptyObject(defaults) && retry !== false) {
@@ -83,6 +83,10 @@ const preNormalize = (options, defaults) => {
8383
options.retry.statusCodes = new Set(options.retry.statusCodes);
8484
}
8585

86+
if (is.array(options.retry.errorCodes)) {
87+
options.retry.errorCodes = new Set(options.retry.errorCodes);
88+
}
89+
8690
return options;
8791
};
8892

@@ -210,7 +214,7 @@ const normalize = (url, options, defaults) => {
210214
return 0;
211215
}
212216

213-
if (!isRetryOnNetworkErrorAllowed(error) && (!options.retry.methods.has(error.method) || !options.retry.statusCodes.has(error.statusCode))) {
217+
if ((!error || !options.retry.errorCodes.has(error.code)) && (!options.retry.methods.has(error.method) || !options.retry.statusCodes.has(error.statusCode))) {
214218
return 0;
215219
}
216220

‎source/utils/is-retry-on-network-error-allowed.js

-20
This file was deleted.

‎test/retry.js

+33
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import http from 'http';
12
import test from 'ava';
23
import pEvent from 'p-event';
34
import got from '../source';
@@ -151,6 +152,38 @@ test('custom retries', async t => {
151152
t.true(tried);
152153
});
153154

155+
test('custom errors', async t => {
156+
const errorCode = 'OH_SNAP';
157+
158+
let isTried = false;
159+
const error = await t.throwsAsync(got(`${s.url}/500`, {
160+
request: (...args) => {
161+
const request = http.request(...args);
162+
if (!isTried) {
163+
isTried = true;
164+
const error = new Error('Snap!');
165+
error.code = errorCode;
166+
167+
setTimeout(() => request.emit('error', error));
168+
}
169+
170+
return request;
171+
},
172+
retry: {
173+
retries: 1,
174+
methods: [
175+
'GET'
176+
],
177+
errorCodes: [
178+
errorCode
179+
]
180+
}
181+
}));
182+
183+
t.is(error.statusCode, 500);
184+
t.true(isTried);
185+
});
186+
154187
test('respect 413 Retry-After', async t => {
155188
const {statusCode, body} = await got(`${s.url}/measure413`, {
156189
throwHttpErrors: false,

0 commit comments

Comments
 (0)
Please sign in to comment.