Skip to content

Commit 99bef89

Browse files
committed
feat: use undici to download binary
1 parent 5d03c1d commit 99bef89

File tree

4 files changed

+64
-42
lines changed

4 files changed

+64
-42
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ The following changes only apply when using `sentry-cli` via the npm package [`@
5858

5959
- Fixed misleading error message claiming the server doesn't support chunk uploading when the actual error was a non-existent organization ([#2930](https://github.com/getsentry/sentry-cli/pull/2930)).
6060

61+
### Internal changes
62+
63+
- Removed `node-fetch` dependency when using the NPM package ([#2993](https://github.com/getsentry/sentry-cli/pull/2993))
6164

6265
## 2.58.2
6366

package-lock.json

Lines changed: 39 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@
1515
"sentry-cli": "bin/sentry-cli"
1616
},
1717
"dependencies": {
18-
"https-proxy-agent": "^5.0.0",
19-
"node-fetch": "^2.6.7",
2018
"progress": "^2.0.3",
2119
"proxy-from-env": "^1.1.0",
20+
"undici": "^7.16.0",
2221
"which": "^2.0.2"
2322
},
2423
"devDependencies": {

scripts/install.js

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ const fs = require('fs');
66
const os = require('os');
77
const path = require('path');
88
const crypto = require('crypto');
9-
const zlib = require('zlib');
109
const stream = require('stream');
1110
const process = require('process');
1211

13-
const fetch = require('node-fetch');
14-
const HttpsProxyAgent = require('https-proxy-agent');
12+
const { ProxyAgent, fetch } = require('undici');
1513
const ProgressBar = require('progress');
1614
const Proxy = require('proxy-from-env');
1715
const which = require('which');
@@ -220,7 +218,7 @@ async function downloadBinary() {
220218
}
221219

222220
const proxyUrl = Proxy.getProxyForUrl(downloadUrl);
223-
const agent = proxyUrl ? new HttpsProxyAgent(proxyUrl) : null;
221+
const dispatcher = proxyUrl ? new ProxyAgent(proxyUrl) : undefined;
224222

225223
logger.log(`Downloading from ${downloadUrl}`);
226224

@@ -231,12 +229,8 @@ async function downloadBinary() {
231229
let response;
232230
try {
233231
response = await fetch(downloadUrl, {
234-
agent,
235-
compress: false,
236-
headers: {
237-
'accept-encoding': 'gzip, deflate, br',
238-
},
239232
redirect: 'follow',
233+
dispatcher,
240234
});
241235
} catch (error) {
242236
let errorMsg = `Unable to download sentry-cli binary from ${downloadUrl}.\nError message: ${error.message}`;
@@ -254,39 +248,38 @@ async function downloadBinary() {
254248
throw new Error(errorMsg);
255249
}
256250

257-
const contentEncoding = response.headers.get('content-encoding');
258-
let decompressor;
259-
if (/\bgzip\b/.test(contentEncoding)) {
260-
decompressor = zlib.createGunzip();
261-
} else if (/\bdeflate\b/.test(contentEncoding)) {
262-
decompressor = zlib.createInflate();
263-
} else if (/\bbr\b/.test(contentEncoding)) {
264-
decompressor = zlib.createBrotliDecompress();
265-
} else {
266-
decompressor = new stream.PassThrough();
267-
}
268251
const name = downloadUrl.match(/.*\/(.*?)$/)[1];
269252
let downloadedBytes = 0;
270-
const totalBytes = parseInt(response.headers.get('content-length'), 10);
253+
254+
// Note: content-length might not be available if response was compressed,
255+
// as native fetch decompresses transparently
256+
const contentLength = response.headers.get('content-length');
257+
const totalBytes = contentLength ? parseInt(contentLength, 10) : 0;
271258
const progressBar = createProgressBar(name, totalBytes);
272259
const tempPath = getTempFile(cachedPath);
273260
fs.mkdirSync(path.dirname(tempPath), { recursive: true });
274261

275262
await new Promise((resolve, reject) => {
276-
response.body
263+
// Convert Web ReadableStream to Node.js stream
264+
const nodeStream = stream.Readable.fromWeb(response.body);
265+
266+
nodeStream
277267
.on('error', (e) => reject(e))
278268
.on('data', (chunk) => {
279269
downloadedBytes += chunk.length;
280-
progressBar.tick(chunk.length);
270+
271+
if (!progressBar.complete) {
272+
progressBar.tick(chunk.length);
273+
}
281274
})
282-
.pipe(decompressor)
283275
.pipe(fs.createWriteStream(tempPath, { mode: '0755' }))
284276
.on('error', (e) => reject(e))
285-
.on('close', () => {
286-
if (downloadedBytes >= totalBytes) {
287-
resolve();
288-
} else {
277+
.on('finish', () => {
278+
// Check if we have a total size to validate against
279+
if (totalBytes > 0 && downloadedBytes < totalBytes) {
289280
reject(new Error('connection interrupted'));
281+
} else {
282+
resolve();
290283
}
291284
});
292285
});

0 commit comments

Comments
 (0)