0

I have a site with a service worker (mainly for the purpose of offline function of PWA).

The service worker's sole purpose is to listen to fetch events from the page, cache or retrieve from the cache, and then respond.

Unfortunately, because I wanted a request for a specific file extension to be treated differently, I end up having an empty body in the cache.

this is the code for my service worker:

self.addEventListener('fetch', function(event){
  event.respondWith(async function(){
    if(event.request.url.endsWith(".tyc")){
      var cacheMatch = await caches.match(event.request);
      if(cacheMatch){
        debugger;
        cacheMatch.arrayBuffer().then((arrBuf)=>{
          console.debug("got from cache:", arrBuf);
        });
        return cacheMatch;
      }
      var res = await fetch(event.request);
      console.debug("fetched:", res);
      var cache = await caches.open('cache');
      console.debug("got cache:", cache);
      console.debug("cached:", cache.put(event.request.url, res.clone()));
      return res;
    }else{
      try{
        var res = await fetch(event.request);
        var cache = await caches.open('cache');
        cache.put(event.request.url, res.clone());
        return res;
      }catch{
        return caches.match(event.request);
      } 
    }
  }());
});

I tried logging everything possible to figure this out myself, but i don't understand why it doesn't work.

Explanation of whats expected of the code:

Note: the else statement was taken from SO on another question. Before adding the if statement (and else statement), the content of the else statement was the entire code. I based the if true code on the SO answer i found.

if the url ends in .tyc

Look for a matching cache and if there is one, return it. otherwise fetch, create a cache and return the response.

(I want to look for a cache first, because the .tyc file in mind tends to be particularly large)

the else statement:

Try to fetch the url, return it, and update/create the associated cache (To keep the cache up to date). if an error is thrown, assume an offline network and send an available cached resource.

Explanation of what happened:

the else statement:

the right thing

if the url ends in .tyc

do the right thing, but instead of caching the body, only cache the headers, and return a pointless response.



I even try deleting the cache, but after the next reload (in which the cache has been saved by then), the cache body remains empty. I even took a look in DevTools > Application > Cache and see that the .tyc urls show 'Nothing to preview' while all other files do. I note that it is a binary file, but still, I am sure Chrome doesn't care, and shows the control-character glyphs anyway, but nothing... even evaluating

await (await fetch('https://example.com/default_3.7_7ea402.tyc')).arrayBuffer() shows

ArrayBuffer(0)
got from cache: ArrayBuffer(0)                                       serviceworker.js:8 
eac
  • 61
  • 4

1 Answers1

1

I realized 15 hours later that I was caching HEAD requests before ever caching GET requests

and after fixing that, i had to deal with a locked response from line 7 by adding clone(), but After having fixed the issue, I no longer need debugging lines.

So the answer for anyone else who has code on their website (not in the service worker) that makes a HEAD request, and directly after, makes a GET request, and does something I may want to do, which is retrieve cache before fetching,

simply check if the request is a HEAD request before caching, and if it is, don't cache.

So here is the fixed code with fixed debugging code too

self.addEventListener('fetch', function(event){
  event.respondWith(async function(){
    if(event.request.url.endsWith(".tyc")){
      var cacheMatch = await caches.match(event.request);
      if(cacheMatch){
        //clone() because the body's already used////////
        cacheMatch.clone().arrayBuffer().then((arrBuf)=>{
          console.debug("got from cache:", arrBuf);
        });
        return cacheMatch;
      }
      var res = await fetch(event.request);
      ////////The line I added below////////
      if(event.request.method.toLowerCase() === "head"){
        return res;
      }
      ////////^^^^^^^^^^^^^^^^^^^^^^////////
      console.debug("fetched:", res);
      var cache = await caches.open('cache');
      console.debug("got cache:", cache);
      console.debug("cached:", cache.put(event.request.url, res.clone()));
      return res;
    }else{
      try{
        var res = await fetch(event.request);
        var cache = await caches.open('cache');
        cache.put(event.request.url, res.clone());
        return res;
      }catch{
        return caches.match(event.request);
      } 
    }
  }());
});
eac
  • 61
  • 4