Workers Cache API (solved)

Updated, working code

(function () {
  'use strict';

  addEventListener('fetch', (event) => {
      event.respondWith(handleEvent(event));
  });
  const handleEvent = async (event) => {
      const originalRequest = event.request;
      const matchRequest = originalRequest;
      console.log(`Got request for ${event.request.url}`);
      let cache = caches.default;
      let response = await cache.match(matchRequest);
      if (response) {
          return response;
      }
      else {
          response = await handleNewRequest(originalRequest);
          event.waitUntil(Promise.all([
              buildCacheResponse(cache, matchRequest, response)
          ]));
          return response;
      }
  };
  /**
   * @param {Request} originalRequest
   */
  const handleNewRequest = async (originalRequest) => {
      console.log('answering from origin');
      const originResponse = await fetch(originalRequest);
      const responseClientPassThroughStream = new TransformStream();
      originResponse.body.pipeTo(responseClientPassThroughStream.writable);
      // build response for client
      const clientHeaders = new Headers();
      for (const kv of originResponse.headers.entries()) {
          clientHeaders.append(kv[0], kv[1]);
      }
      clientHeaders.append('SERVEZONE_ROUTE', 'Cloudflare_EDGE_ORIGIN_INITIAL');
      const responseForClient = new Response(responseClientPassThroughStream.readable, Object.assign({}, originResponse, { headers: clientHeaders }));
      // lets return the responses
      return responseForClient;
  };
  const buildCacheResponse = async (cache, matchRequest, originResponse) => {
      const cacheHeaders = new Headers();
      for (const kv of originResponse.headers.entries()) {
          cacheHeaders.append(kv[0], kv[1]);
      }
      cacheHeaders.delete('SERVEZONE_ROUTE');
      cacheHeaders.append('SERVEZONE_ROUTE', 'Cloudflare_EDGE_CACHE');
      cacheHeaders.delete('Cache-Control');
      cacheHeaders.append('Cache-Control', 'public, max-age=600');
      cacheHeaders.delete('Expires');
      cacheHeaders.append('Expires', new Date(Date.now() + 600 * 1000).toUTCString());
      const responseForCache = new Response(await originResponse.clone().text(), Object.assign({}, originResponse, { headers: cacheHeaders }));
      await cache.put(matchRequest, responseForCache);
  };

}());
2 Likes

I use it like this:

let cache = caches.default
let response = await cache.match(event.request.url) 
if (response) {
          return response;
      }

Instead of:
event.waitUntil(Promise.all([cache.put(matchRequest, responses.responseForCache.clone())]));

Why not?

event.waitUntil(cache.put(event.request.url, responses.responseForCache.clone()));

PS: answering from mobile, might have missed something.

1 Like

actually the problem is the stream cloning and the way backpressure is handled within streams. I fixed it and now it works. :slight_smile: Thank you for your time.

Great. Can you show your solution?

Yes, the original question has the updated code.