7
votes

I have a website which I don't want to make people create accounts. It is a news feed with each news article categorized. I want to allow people to tag the categories they are interested in so that next time they go to the site it only shows news for the categories that are tagged.

I'm saving the tags in an indexedDB which I understand is available in a service worker.

Hence in my service worker I want to "intercept" requests to www.my-url.com, check the indexDB for what categories this person is interested in, and add some headers like 'x-my-customer-header': 'technology,physics,sports' so that my server can respond with a dynamic html of those categories only.

However I'm struggling to get the service worker to properly cache my root response. In my serviceworker.js, I console log every event.request for the onFetch handler. There are no requests that are related to my root url. I'm testing right now on my localhost, but I only see fetch requests to css & js files.

Here is my onFetch:

function onFetch(event) {
  console.log('onFetch',event.request.url);
  event.request.headers["X-my-custom-header"] = "technology,sports";
  event.respondWith(
    // try to return untouched request from network first
    fetch(event.request).catch(function() {
      // if it fails, try to return request from the cache
      caches.match(event.request).then(function(response) {
        if (response) {
          return response;
        }
        // if not found in cache, return default offline content for navigate requests
        if (event.request.mode === 'navigate' ||
          (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) {
          return caches.match('/offline.html');
        }
      })
    })
  );
}

I'm using rails so there is no index.html that exists to be cached, when a user hits my url, the page is dynamically served from my news#controller.

I'm actually using the gem serviceworker-rails

What am I doing wrong? How can I have my service worker save a root file and intercept the request to add headers? Is this even possible?

1
but do you see the other requests in chrome dev tools?Stef Chäser
@StefChäser yes. I think my issue is that rails dynamically produces localhost so there is no index.html? Not entirely sure...Terence Chow
By the way, I think it is not a good idea to handle categories in the service worker, since it is application logic. (what if the browser doesn't support sw) And be aware that caches.match(event.request) does not compare the headers, so if you have a cached request for "technology,sports" it will also match if the user changes it to "technology,beer". Better handle the categories with url params.Stef Chäser
Did you check if the service worker runs in the correct scope: stackoverflow.com/questions/35780397/…Stef Chäser
@StefChäser yes I am operating on the root scope.Terence Chow

1 Answers

11
votes

Credit here goes to Jeff Posnick for his answer on constructing a new Request. You'll need to respond with a fetch that creates a new Request to which you can add headers:

self.addEventListener('fetch', event => {
  event.respondWith(customHeaderRequestFetch(event))
})

function customHeaderRequestFetch(event) {
  // decide for yourself which values you provide to mode and credentials
  const newRequest = new Request(event.request, {
    mode: 'cors',
    credentials: 'omit',
    headers: {
      'x-my-custom-header': 'The Most Amazing Header Ever'
    }
  })
  return fetch(newRequest)
}