(url, dest, redirectsLeft)
| 175 | |
| 176 | // GET with manual redirect following (GitHub release URLs redirect to a CDN). |
| 177 | function download(url, dest, redirectsLeft) { |
| 178 | return new Promise(function (resolve, reject) { |
| 179 | var https = require('https'); |
| 180 | // timeout is an idle/inactivity timeout — it won't kill a slow-but-progressing |
| 181 | // download, only a stalled connection (so a blocked mirror fails fast with |
| 182 | // guidance instead of hanging the user's command forever). |
| 183 | var req = https.get(url, { headers: { 'User-Agent': 'codegraph-npm-shim' }, timeout: 30000 }, function (res) { |
| 184 | var status = res.statusCode; |
| 185 | if (status >= 300 && status < 400 && res.headers.location) { |
| 186 | res.resume(); |
| 187 | if (redirectsLeft <= 0) { reject(new Error('too many redirects')); return; } |
| 188 | download(new URL(res.headers.location, url).toString(), dest, redirectsLeft - 1).then(resolve, reject); |
| 189 | return; |
| 190 | } |
| 191 | if (status !== 200) { res.resume(); reject(new Error('HTTP ' + status)); return; } |
| 192 | var file = fs.createWriteStream(dest); |
| 193 | res.on('error', reject); |
| 194 | res.pipe(file); |
| 195 | file.on('error', reject); |
| 196 | file.on('finish', function () { file.close(function () { resolve(); }); }); |
| 197 | }); |
| 198 | req.on('timeout', function () { req.destroy(new Error('connection timed out')); }); |
| 199 | req.on('error', reject); |
| 200 | }); |
| 201 | } |
| 202 | |
| 203 | // Best-effort integrity check. When the release publishes a SHA256SUMS file, the |
| 204 | // downloaded archive MUST match its listed hash or we abort. When that file is |
no test coverage detected