Issue encountered when exposing an R2 bucket through a worker

For Workers & Pages, what is the name of the domain?

example.com

What is the issue or error you’re encountering

To count the number of downloads for a specific file in R2 bucket.

What steps have you taken to resolve the issue?

There are several static files that users download through R2. When using R2 directly to provide downloads, it is impossible to count the number of downloads for each file accurately(eg. APP’s Installer download count).

Exposing the R2 bucket through a worker allows for counting, but some problems have been encountered:

  1. The first is that after providing the download through the worker, the download speed of the same file will be much slower than using R2 directly. The reason is that the CDN can no longer be used.

  2. Another problem is that when using a worker to serve files, if I use the Stream APIs, I cannot set the content-length and content-type in the response header when responding. After searching for a long time, I found that there may be a problem with the worker SDK. I am not sure if my understanding is correct.

What are the steps to reproduce the issue?

Here is the example code:

app.get('/downloads/:assetname', async (c) => {
    const obj = await c.env.R2_BUCKET.get(assetName)

    // ...

    const headers = new Headers()
    obj.writeHttpMetadata(headers)

    const { readable, writable } = new TransformStream({
	async start(controller) {
		console.log("started and count + 1")
	},
	async transform(chunk, controller) {
		controller.enqueue(chunk);
	},
	async flush(controller) {
		console.log("flushed, and sent + 1")
	},
    });
    obj.body.pipeTo(writable)
    return new Response(readable, {
	headers: headers,
	status: 200,
    })
})

If I just use the following and do file count inside middleware, everything works fine:

const obj = await c.env.R2_BUCKET.get(assetName)

c.status(200)
c.header('etag', obj.httpEtag) 
return c.body(obj.body)