diff --git a/packages/lib-infer-diffusion/test/integration/utils.js b/packages/lib-infer-diffusion/test/integration/utils.js index c4959d2b56..d0e562b61e 100644 --- a/packages/lib-infer-diffusion/test/integration/utils.js +++ b/packages/lib-infer-diffusion/test/integration/utils.js @@ -38,12 +38,7 @@ async function downloadFile (url, dest) { return safeReject(unlinkErr) } - let redirectUrl = response.headers.location - // Handle relative redirects - if (redirectUrl.startsWith('/')) { - const originalUrl = new URL(url) - redirectUrl = `${originalUrl.protocol}//${originalUrl.host}${redirectUrl}` - } + const redirectUrl = new URL(response.headers.location, url).href downloadFile(redirectUrl, dest) .then(safeResolve) diff --git a/packages/qvac-lib-infer-llamacpp-embed/examples/utils.js b/packages/qvac-lib-infer-llamacpp-embed/examples/utils.js index aa02e9862c..2137d2a36a 100644 --- a/packages/qvac-lib-infer-llamacpp-embed/examples/utils.js +++ b/packages/qvac-lib-infer-llamacpp-embed/examples/utils.js @@ -19,28 +19,45 @@ async function downloadModel (url, filename) { console.log(`Downloading ${filename}...`) return new Promise((resolve, reject) => { + let resolved = false + const safeResolve = (val) => { if (!resolved) { resolved = true; resolve(val) } } + const safeReject = (err) => { if (!resolved) { resolved = true; reject(err) } } + const fileStream = fs.createWriteStream(modelPath) - let downloaded = 0 + + fileStream.on('error', (err) => { + fileStream.destroy() + fs.unlink(modelPath, () => safeReject(err)) + }) const req = https.request(url, response => { - if (response.statusCode === 301 || response.statusCode === 302) { + if ([301, 302, 307, 308].includes(response.statusCode)) { fileStream.destroy() req.destroy() response.destroy() - fs.unlink(modelPath, () => {}) - return downloadModel(response.headers.location, filename) - .then(resolve).catch(reject) + fs.unlink(modelPath, (unlinkErr) => { + if (unlinkErr && unlinkErr.code !== 'ENOENT') { + return safeReject(unlinkErr) + } + + const redirectUrl = new URL(response.headers.location, url).href + + downloadModel(redirectUrl, filename) + .then(safeResolve).catch(safeReject) + }) + return } if (response.statusCode !== 200) { fileStream.destroy() req.destroy() response.destroy() - fs.unlink(modelPath, () => {}) - return reject(new Error(`Download failed: ${response.statusCode}`)) + fs.unlink(modelPath, () => safeReject(new Error(`Download failed: ${response.statusCode}`))) + return } const total = parseInt(response.headers['content-length'], 10) + let downloaded = 0 response.on('data', chunk => { downloaded += chunk.length @@ -52,20 +69,21 @@ async function downloadModel (url, filename) { } }) + response.on('error', (err) => { + fileStream.destroy() + fs.unlink(modelPath, () => safeReject(err)) + }) + response.pipe(fileStream) fileStream.on('close', () => { - fileStream.destroy() - req.destroy() - response.destroy() console.log('\nDownload complete!') - resolve([filename, modelDir]) + safeResolve([filename, modelDir]) }) }) req.on('error', err => { fileStream.destroy() - req.destroy() - fs.unlink(modelPath, () => reject(err)) + fs.unlink(modelPath, () => safeReject(err)) }) req.end() diff --git a/packages/qvac-lib-infer-llamacpp-embed/test/integration/utils.js b/packages/qvac-lib-infer-llamacpp-embed/test/integration/utils.js index cd535b0594..50c64aecc3 100644 --- a/packages/qvac-lib-infer-llamacpp-embed/test/integration/utils.js +++ b/packages/qvac-lib-infer-llamacpp-embed/test/integration/utils.js @@ -15,39 +15,53 @@ const FilesystemDL = require('@qvac/dl-filesystem') */ async function downloadFile (url, dest) { return new Promise((resolve, reject) => { + let resolved = false + const safeResolve = () => { if (!resolved) { resolved = true; resolve() } } + const safeReject = (err) => { if (!resolved) { resolved = true; reject(err) } } + const file = fs.createWriteStream(dest) + + file.on('error', (err) => { + file.destroy() + fs.unlink(dest, () => safeReject(err)) + }) + const req = https.request(url, (response) => { - // Handle redirects (301, 302, 307, 308 for Windows model download) if ([301, 302, 307, 308].includes(response.statusCode)) { file.destroy() - fs.unlink(dest, () => {}) // Clean up partial file + fs.unlink(dest, (unlinkErr) => { + if (unlinkErr && unlinkErr.code !== 'ENOENT') { + return safeReject(unlinkErr) + } - let redirectUrl = response.headers.location - // Handle relative redirects - if (redirectUrl.startsWith('/')) { - const originalUrl = new URL(url) - redirectUrl = `${originalUrl.protocol}//${originalUrl.host}${redirectUrl}` - } + const redirectUrl = new URL(response.headers.location, url).href - return downloadFile(redirectUrl, dest).then(resolve).catch(reject) + downloadFile(redirectUrl, dest) + .then(safeResolve).catch(safeReject) + }) + return } if (response.statusCode !== 200) { file.destroy() - fs.unlink(dest, () => {}) - return reject(new Error(`Download failed: ${response.statusCode}`)) + fs.unlink(dest, () => safeReject(new Error(`Download failed: ${response.statusCode}`))) + return } - response.pipe(file) - file.on('finish', () => { + response.on('error', (err) => { file.destroy() - resolve() + fs.unlink(dest, () => safeReject(err)) + }) + + response.pipe(file) + file.on('close', () => { + safeResolve() }) }) req.on('error', (err) => { file.destroy() - fs.unlink(dest, () => reject(err)) + fs.unlink(dest, () => safeReject(err)) }) req.end() diff --git a/packages/qvac-lib-infer-llamacpp-llm/examples/utils.js b/packages/qvac-lib-infer-llamacpp-llm/examples/utils.js index aa02e9862c..2137d2a36a 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/examples/utils.js +++ b/packages/qvac-lib-infer-llamacpp-llm/examples/utils.js @@ -19,28 +19,45 @@ async function downloadModel (url, filename) { console.log(`Downloading ${filename}...`) return new Promise((resolve, reject) => { + let resolved = false + const safeResolve = (val) => { if (!resolved) { resolved = true; resolve(val) } } + const safeReject = (err) => { if (!resolved) { resolved = true; reject(err) } } + const fileStream = fs.createWriteStream(modelPath) - let downloaded = 0 + + fileStream.on('error', (err) => { + fileStream.destroy() + fs.unlink(modelPath, () => safeReject(err)) + }) const req = https.request(url, response => { - if (response.statusCode === 301 || response.statusCode === 302) { + if ([301, 302, 307, 308].includes(response.statusCode)) { fileStream.destroy() req.destroy() response.destroy() - fs.unlink(modelPath, () => {}) - return downloadModel(response.headers.location, filename) - .then(resolve).catch(reject) + fs.unlink(modelPath, (unlinkErr) => { + if (unlinkErr && unlinkErr.code !== 'ENOENT') { + return safeReject(unlinkErr) + } + + const redirectUrl = new URL(response.headers.location, url).href + + downloadModel(redirectUrl, filename) + .then(safeResolve).catch(safeReject) + }) + return } if (response.statusCode !== 200) { fileStream.destroy() req.destroy() response.destroy() - fs.unlink(modelPath, () => {}) - return reject(new Error(`Download failed: ${response.statusCode}`)) + fs.unlink(modelPath, () => safeReject(new Error(`Download failed: ${response.statusCode}`))) + return } const total = parseInt(response.headers['content-length'], 10) + let downloaded = 0 response.on('data', chunk => { downloaded += chunk.length @@ -52,20 +69,21 @@ async function downloadModel (url, filename) { } }) + response.on('error', (err) => { + fileStream.destroy() + fs.unlink(modelPath, () => safeReject(err)) + }) + response.pipe(fileStream) fileStream.on('close', () => { - fileStream.destroy() - req.destroy() - response.destroy() console.log('\nDownload complete!') - resolve([filename, modelDir]) + safeResolve([filename, modelDir]) }) }) req.on('error', err => { fileStream.destroy() - req.destroy() - fs.unlink(modelPath, () => reject(err)) + fs.unlink(modelPath, () => safeReject(err)) }) req.end() diff --git a/packages/qvac-lib-infer-llamacpp-llm/test/integration/utils.js b/packages/qvac-lib-infer-llamacpp-llm/test/integration/utils.js index f924f963c0..85da4d4fd7 100644 --- a/packages/qvac-lib-infer-llamacpp-llm/test/integration/utils.js +++ b/packages/qvac-lib-infer-llamacpp-llm/test/integration/utils.js @@ -39,12 +39,7 @@ async function downloadFile (url, dest) { return safeReject(unlinkErr) } - let redirectUrl = response.headers.location - // Handle relative redirects - if (redirectUrl.startsWith('/')) { - const originalUrl = new URL(url) - redirectUrl = `${originalUrl.protocol}//${originalUrl.host}${redirectUrl}` - } + const redirectUrl = new URL(response.headers.location, url).href downloadFile(redirectUrl, dest) .then(safeResolve)