I created a script that puts a list of files into a zip and saves it on in the Cloudflare R2 bucket. The scripts runs until the archive gets closed, after that, it throws the error: Error: The script will never generate a response.
As you see, I catch every possible response, but still, I get this error. Any ideas why?
import { z } from 'zod';
import { ZipWriter, BlobReader, configure } from '@zip.js/zip.js';
// Without this, we get uncaught error due to Workers runtime bug
// See: https://github.com/gildas-lormeau/zip.js/discussions/514
configure({
useCompressionStream: false,
});
// Payload schema that lists the files to be bundled, their filenames and the archive filename
const schema = z.object({
archive_filename: z.string().endsWith('.zip'),
files: z.array(
z.object({
r2key: z.string(),
filename: z.string(),
})
),
});
export default {
async fetch(request, env, ctx): Promise<Response> {
// Only POST is supported
if (request.method !== 'POST') {
return new Response('Method Not Allowed', { status: 405 });
}
const body = await request.json();
const payload = schema.safeParse(body);
if (!payload.success) {
return new Response(JSON.stringify({ status: 'failed', error: payload.error }), {
status: 409,
headers: { 'Content-Type': 'application/json' },
});
}
// Use IdentityTransformStream to capture the zip output
let { readable, writable } = new IdentityTransformStream();
// Create a ZIP archive stream
const archive = new ZipWriter(writable);
// Store all the promises to catch any errors all together later
let promises: Promise<any>[] = [];
console.log(payload);
for (const somefile of payload.data.files) {
const { r2key, filename } = somefile;
console.log(r2key);
console.log(filename);
// Fetch the file from the R2 bucket
const fileContent = await env.STORAGE_BUCKET_DEV.get(r2key);
if (!fileContent) {
return new Response(`Object not found: ${r2key}`, { status: 404 });
}
// Add the file to the ZIP archive
promises.push(archive.add(filename, new BlobReader(await fileContent.blob())));
console.log("Item added");
}
// Close the archive
promises.push(archive.close());
//Everything works till here.
try {
// Wait for all files to be added and the archive to be closed
await Promise.all(promises);
// Save the ZIP archive to the bucket
const key = `downloads/${payload.data.archive_filename}`;
await env.STORAGE_BUCKET_DEV.put(key, readable, {
httpMetadata: { contentType: 'application/zip' },
});
// Return the download URL
const url = new URL(request.url);
url.pathname = `/${key}`;
return new Response(JSON.stringify({ url: url.toString() }), {
headers: { 'Content-Type': 'application/json' },
});
} catch (err) {
return new Response(
JSON.stringify({ status: 'error', message: err.toString() }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
},
} satisfies ExportedHandler<Env>;