From 8abd34278cc08072b64bb1d9b784ff7e431f393c Mon Sep 17 00:00:00 2001 From: David Sanders Date: Sun, 12 Apr 2026 12:26:07 -0700 Subject: [PATCH] chore: retry downloads on retryable errors Assisted-by: Claude Opus 4.6 Signed-off-by: David Sanders --- lib/download.js | 3 ++- test/test-download.js | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/download.js b/lib/download.js index ed0aa37f44..b41ebdfeb3 100644 --- a/lib/download.js +++ b/lib/download.js @@ -11,7 +11,8 @@ async function download (gyp, url) { Connection: 'keep-alive' }, proxy: gyp.opts.proxy, - noProxy: gyp.opts.noproxy + noProxy: gyp.opts.noproxy, + retry: 3 } const cafile = gyp.opts.cafile diff --git a/test/test-download.js b/test/test-download.js index a746c98cc6..48639c46b2 100644 --- a/test/test-download.js +++ b/test/test-download.js @@ -153,6 +153,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 () {