The exported R2 worker `fetch` function *shadows* the native JS `fetch`

Hi there!

I’m trying to write an R2 worker that fetches content from an external site before uploading it into R2 (or into cache if already in R2).

The trouble seems to be - the R2 API requires that I export a function which shadows the native fetch function.

How can I invoke the native JS fetch function from instead the shadowed version?

I don’t really understand what you mean by a fetch function exported or used by R2 - are you using a community library?

I have a Module-based JS worker which is bound to an R2 bucket and to a service endpoint.

When the worker is activated, I want it to parse my url and use that to look up a blob which might exist already in R2. If the blob doesn’t exist, it should fetch that blob from a different website. For this, I am trying to use the standard JS fetch API.

The problem is - for the worker to be activated, I’m exporting my own fetch method in the default namespace. Obviously, this creates an infinite recursion when I try to fetch within my own fetch method.

Do I have to use a different type of worker to be able to fetch natively?

export default {
  async fetch(request, env) {
    fetch('https://foo.bar/package.zip')  // RECURSION
      .then((response) => response.text())
      .then(console.log);
  }
}

That’s not an issue in Workers - what makes you think it’s calling the exported fetch function?

I’m looking at wrangler output when I hit my local endpoint. I see a terminal full of console logging statements before it crashes with:

FETCHING GLOBAL https://getfedora.org/ undefined
FETCHING GLOBAL https://getfedora.org/ undefined
FETCHING GLOBAL https://getfedora.org/ undefined
[mf:err] GET /favicon.ico: RangeError: Maximum call stack size exceeded
    at formatPrimitive (node:internal/util/inspect:1519:25)
    at formatValue (node:internal/util/inspect:750:12)
    at inspect (node:internal/util/inspect:347:10)
    at formatWithOptionsInternal (node:internal/util/inspect:2167:40)
    at formatWithOptions (node:internal/util/inspect:2029:10)
    at console.value (node:internal/console/constructor:324:14)
    at console.log (node:internal/console/constructor:360:61)
    at fetch (/code/src/index.mjs:131:11)
    at fetch (/code/src/index.mjs:133:9)
    at fetch (/code/src/index.mjs:133:9)

I figured out what I was doing wrong. JS is not my first language, so this was a stupid JS rookie mistake.

Here’s what I had:

async function fetch(request, env, ctx) {
  // my code
}
export default {fetch}

This is clearly not equivalent to the documented:

export default {
  async fetch(request, env) {
    // my code
  }
}

I am not sure how my version worked at all. It seems that I accidentally shadowed my own fetch method, and I was still able to invoke the worker through the service endpoint.

Anyway, it works now!

1 Like

Thanks for helping, BTW, @KianNH!

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.