diff --git a/lib/download.js b/lib/download.js index a9866d8a63..0d9d2e32fa 100644 --- a/lib/download.js +++ b/lib/download.js @@ -1,5 +1,5 @@ const { Readable } = require('stream') -const { EnvHttpProxyAgent } = require('undici') +const { Agent, EnvHttpProxyAgent, RetryAgent } = require('undici') const { promises: fs } = require('graceful-fs') const log = require('./log') @@ -48,7 +48,7 @@ async function createDispatcher (gyp) { const env = process.env const hasProxyEnv = env.http_proxy || env.HTTP_PROXY || env.https_proxy || env.HTTPS_PROXY if (!gyp.opts.proxy && !gyp.opts.cafile && !hasProxyEnv) { - return undefined + return new RetryAgent(new Agent(), { maxRetries: 3 }) } const opts = {} @@ -69,7 +69,7 @@ async function createDispatcher (gyp) { if (gyp.opts.noproxy) { opts.noProxy = gyp.opts.noproxy } - return new EnvHttpProxyAgent(opts) + return new RetryAgent(new EnvHttpProxyAgent(opts), { maxRetries: 3 }) } async function readCAFile (filename) { diff --git a/test/test-download.js b/test/test-download.js index 4078efe5cd..756142f623 100644 --- a/test/test-download.js +++ b/test/test-download.js @@ -218,6 +218,32 @@ describe('download', function () { assert.notStrictEqual(cas[0], cas[1]) }) + it('download will retry on ECONNRESET', async function () { + let requestCount = 0 + const server = http.createServer((req, res) => { + requestCount++ + if (requestCount < 3) { + req.socket.destroy() + return + } + res.end('ok') + }) + + after(() => new Promise((resolve) => server.close(resolve))) + + const host = 'localhost' + await new Promise((resolve) => server.listen(0, host, resolve)) + const { port } = server.address() + const gyp = { + opts: {}, + version: '42' + } + const url = `http://${host}:${port}` + const res = await download(gyp, url) + assert.strictEqual(await res.text(), 'ok') + assert.ok(requestCount >= 2, `expected at least 2 requests but got ${requestCount}`) + }) + // only run this test if we are running a version of Node with predictable version path behavior it('download headers (actual)', async function () {