diff --git a/lib/handler/retry-handler.js b/lib/handler/retry-handler.js index f469f9df343..07b0ff83e00 100644 --- a/lib/handler/retry-handler.js +++ b/lib/handler/retry-handler.js @@ -277,7 +277,7 @@ class RetryHandler { } onResponseError (controller, err) { - if (!controller || controller.aborted || isDisturbed(this.opts.body)) { + if (controller?.aborted || isDisturbed(this.opts.body)) { this.handler.onResponseError?.(controller, err) return } diff --git a/test/interceptors/retry.js b/test/interceptors/retry.js index 2755f9e5c49..df75a636b8b 100644 --- a/test/interceptors/retry.js +++ b/test/interceptors/retry.js @@ -6,7 +6,7 @@ const { createServer } = require('node:http') const { once } = require('node:events') const { Client, interceptors } = require('../..') -const { retry, redirect } = interceptors +const { retry, redirect, dns } = interceptors test('Should retry status code', async t => { t = tspl(t, { plan: 4 }) @@ -74,6 +74,49 @@ test('Should retry status code', async t => { t.equal(await response.body.text(), 'hello world!') }) +test('Should retry on error code', async t => { + t = tspl(t, { plan: 2 }) + + let counter = 0 + const retryOptions = { + retry: (err, _state, done) => { + if (counter < 5) { + counter++ + setTimeout(done, 500) + } else { + done(err) + } + }, + maxRetries: 5 + } + const requestOptions = { + origin: 'http://localhost:123', + method: 'GET', + path: '/', + headers: { + 'content-type': 'application/json' + } + } + + const client = new Client( + 'http://localhost:123' + ).compose(dns({ + lookup: (_h, _o, cb) => { + const error = new Error('ENOTFOUND') + error.code = 'ENOTFOUND' + + cb(error) + } + }), retry(retryOptions)) + + after(async () => { + await client.close() + }) + + await t.rejects(client.request(requestOptions), { code: 'ENOTFOUND' }) + t.equal(counter, 5) +}) + test('Should use retry-after header for retries', async t => { t = tspl(t, { plan: 3 })