@@ -4,6 +4,7 @@ import { spawn } from "node:child_process";
|
4 | 4 | import { createHash } from "node:crypto"; |
5 | 5 | import { lookup as dnsLookupCb } from "node:dns"; |
6 | 6 | import { lookup as dnsLookup } from "node:dns/promises"; |
| 7 | +import { once } from "node:events"; |
7 | 8 | import { createWriteStream } from "node:fs"; |
8 | 9 | import fs from "node:fs/promises"; |
9 | 10 | import { request as httpsRequest } from "node:https"; |
@@ -1165,6 +1166,7 @@ async function* limitWebResponseBody(body, maxBytes, timeoutPromise) {
|
1165 | 1166 | const size = typeof value === "string" ? Buffer.byteLength(value) : value.byteLength; |
1166 | 1167 | downloaded += size; |
1167 | 1168 | if (downloaded > maxBytes) { |
| 1169 | +await reader.cancel().catch(() => {}); |
1168 | 1170 | throw new Error(`package_url exceeds maximum download size of ${maxBytes} bytes`); |
1169 | 1171 | } |
1170 | 1172 | yield value; |
@@ -1199,6 +1201,7 @@ export async function downloadUrl(url, target, options = {}) {
|
1199 | 1201 | options, |
1200 | 1202 | ); |
1201 | 1203 | const tempTarget = `${target}.tmp`; |
| 1204 | +let output; |
1202 | 1205 | try { |
1203 | 1206 | if (!responseOk(response) || !response.body) { |
1204 | 1207 | throw new Error(`failed to download package_url: HTTP ${responseStatus(response)}`); |
@@ -1210,10 +1213,8 @@ export async function downloadUrl(url, target, options = {}) {
|
1210 | 1213 | throw new Error(`package_url exceeds maximum download size of ${maxBytes} bytes`); |
1211 | 1214 | } |
1212 | 1215 | await fs.rm(tempTarget, { force: true }); |
1213 | | -await pipeline( |
1214 | | -limitResponseBody(response.body, maxBytes, timeoutPromise), |
1215 | | -createWriteStream(tempTarget), |
1216 | | -); |
| 1216 | +output = createWriteStream(tempTarget); |
| 1217 | +await pipeline(limitResponseBody(response.body, maxBytes, timeoutPromise), output); |
1217 | 1218 | await fs.rename(tempTarget, target); |
1218 | 1219 | } catch (error) { |
1219 | 1220 | if (error?.code === "ETIMEDOUT") { |
@@ -1228,6 +1229,9 @@ export async function downloadUrl(url, target, options = {}) {
|
1228 | 1229 | } finally { |
1229 | 1230 | clearTimeout(timeout); |
1230 | 1231 | await close(); |
| 1232 | +if (output && !output.closed) { |
| 1233 | +await once(output, "close").catch(() => {}); |
| 1234 | +} |
1231 | 1235 | await fs.rm(tempTarget, { force: true }); |
1232 | 1236 | } |
1233 | 1237 | } |
|