Differences between fetch() and env.ASSETS.fetch()

Is there any documentation on the differences between these two functions? I'm migrating a site from Workers to Pages (with functions), and I'm seeing test failures that I tracked down to subtle differences between how these two methods handle ETag headers. For example, it looks like fetch() will strip ETag headers by default, whereas env.ASSETS.fetch() will not. It's easy enough for me to remove the ETag header myself, but I'm concerned that there are other behavior differences that I might not be aware of.
11 Replies
Philip Walton
Philip WaltonOP6mo ago
I also just noticed that responses served from Pages functions do not contain the Cf-Cache-Status header, whereas responses served from my old Worker file did. That header was useful to determine my cache hit ratio. Is there a configuration option I can set to add that header back?
error_log
error_log6mo ago
Cloudflare Docs
Service bindings - Runtime APIs · Cloudflare Workers docs
Facilitate Worker-to-Worker communication.
Cloudflare Docs
Fetch · Cloudflare Workers docs
An interface for asynchronously fetching resources via HTTP requests inside of a Worker.
Philip Walton
Philip WaltonOP6mo ago
Thanks for the links @cocosrobal but those resources don't cover the differences between the two fetch() methods, nor do they explain why env.ASSETS.fetch() would have different behavior when it comes to ETag and Cf-Cache-Status headers.
Philip Walton
Philip WaltonOP6mo ago
Here's an example of the headers I see when using fetch():
No description
Philip Walton
Philip WaltonOP6mo ago
And then here's an example requesting the exact same resource, but using env.ASSETS.fetch():
No description
Philip Walton
Philip WaltonOP6mo ago
Notice how the first screenshot includes the Cf-Cache-Status header (but no ETag header). And the second screenshot includes the ETag header, but no Cf-Cache-Status header. The first example also retains the X-Cache X-Cache-Hits X-Served-By and X-Timer headers from the origin server, whereas the second example strips those headers.
Walshy
Walshy6mo ago
fetch is https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch ASSETS.fetch is a Pages API for fetching assets. It does not fetch an origin or anything, it's just for fetching static assets It will run through the Pages serving things so add etag, headers, handle redirects, etc.
Philip Walton
Philip WaltonOP6mo ago
ASSETS.fetch is a Pages API for fetching assets. It does not fetch an origin or anything, it's just for fetching static assets
This is not quite true, as both of the screenshots I mentioned above were from assets fetched from an external origin. So both fetch() and env.ASSETS.fetch() support that, they just have different behavior. It sounds like the answer to my question is that "no" there is no documentation that explains the difference. I'd like to suggest that there should be.
Walshy
Walshy6mo ago
env.ASSETS does not fetch origins, if it does that's a problem. It runs our asset serving path which will handle everything We don't do any external fetches in that path that I'm aware of. from your description though it didn't sound like it hit an origin - if you have a url i can hit i can verify what's going on
Philip Walton
Philip WaltonOP6mo ago
Ok, I just checked with the following code:
export async function onRequestGet(context) {
return context.env.ASSETS.fetch('https://example.com');
}
export async function onRequestGet(context) {
return context.env.ASSETS.fetch('https://example.com');
}
This code doesn't error, but it looks like it actually is fetching the / path from the assets. (I.e. the "origin part of the URL is ignored and only the "pathname" part is used.) I didn't notice a difference before because my external origin had the same content as my pages account. Regarding my question about Cf-Cache-Status is threre any way to determine whether there was a cache hit when requesting an asset via env.ASSETS.fetch()? Ideally without manually implenting caching via the Cache API? ...or is the assumption that everything is a "cache hit" (even if it's located in another edge node) and the better thing to measure is the time it takes to fetch the response?
Walshy
Walshy6mo ago
That's correct yes, the hostname is essentially just ignored we don't know ourselves when we get a cache hit at all times, it's something we have an open FR for But from my own metrics, we hit cache the vast majority all the time.
Want results from more Discord servers?
Add your server