Skip to content

Commit 0793489

Browse files
authored
fix: retry downloads on retryable errors (#3308)
Assisted-by: Claude Opus 4.6 Signed-off-by: David Sanders <dsanders11@ucsbalum.com>
1 parent b2fcdcd commit 0793489

2 files changed

Lines changed: 29 additions & 3 deletions

File tree

lib/download.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const { Readable } = require('stream')
2-
const { EnvHttpProxyAgent } = require('undici')
2+
const { Agent, EnvHttpProxyAgent, RetryAgent } = require('undici')
33
const { promises: fs } = require('graceful-fs')
44
const log = require('./log')
55

@@ -48,7 +48,7 @@ async function createDispatcher (gyp) {
4848
const env = process.env
4949
const hasProxyEnv = env.http_proxy || env.HTTP_PROXY || env.https_proxy || env.HTTPS_PROXY
5050
if (!gyp.opts.proxy && !gyp.opts.cafile && !hasProxyEnv) {
51-
return undefined
51+
return new RetryAgent(new Agent(), { maxRetries: 3 })
5252
}
5353

5454
const opts = {}
@@ -69,7 +69,7 @@ async function createDispatcher (gyp) {
6969
if (gyp.opts.noproxy) {
7070
opts.noProxy = gyp.opts.noproxy
7171
}
72-
return new EnvHttpProxyAgent(opts)
72+
return new RetryAgent(new EnvHttpProxyAgent(opts), { maxRetries: 3 })
7373
}
7474

7575
async function readCAFile (filename) {

test/test-download.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,32 @@ describe('download', function () {
218218
assert.notStrictEqual(cas[0], cas[1])
219219
})
220220

221+
it('download will retry on ECONNRESET', async function () {
222+
let requestCount = 0
223+
const server = http.createServer((req, res) => {
224+
requestCount++
225+
if (requestCount < 3) {
226+
req.socket.destroy()
227+
return
228+
}
229+
res.end('ok')
230+
})
231+
232+
after(() => new Promise((resolve) => server.close(resolve)))
233+
234+
const host = 'localhost'
235+
await new Promise((resolve) => server.listen(0, host, resolve))
236+
const { port } = server.address()
237+
const gyp = {
238+
opts: {},
239+
version: '42'
240+
}
241+
const url = `http://${host}:${port}`
242+
const res = await download(gyp, url)
243+
assert.strictEqual(await res.text(), 'ok')
244+
assert.ok(requestCount >= 2, `expected at least 2 requests but got ${requestCount}`)
245+
})
246+
221247
// only run this test if we are running a version of Node with predictable version path behavior
222248

223249
it('download headers (actual)', async function () {

0 commit comments

Comments
 (0)