Service Workers and Server-Side Redirects

TLDR

Do not include any dynamic, user-specific, or redirecting URLs in the STATIC_ASSETS of your service worker. Also, make sure to never serve or cache redirected URLs from the service worker.

The app

I am building a Ruby on Rails recipe tracker web app. For the frontend uses the usual Rails stack (ERB templates, Hotwire, etc.) but I have added a service worker for caching on the client side. It pre-caches all URLs in a list called STATIC_ASSETS, and intercepts GET requests for responding with a cached page (if one exists).

The change resulting in the bug

I added a redirect in my Rails app, which redirects / to /recipes by changing the routes. When visiting /, this resulted in errors like this: Response served by service worker has redirections in both Safari and Chrome.

Debugging

So the first mistake I had to fix, was that I was pre-caching /in the STATIC_ASSETS of my service worker. After the route change, / then always returned a 301 status code (mdn: 301 Moved Permanently). But apparently service workers are not allowed to handle navigation requests with redirect responses.

So the fix was to

  • Remove the URL from STATIC_ASSETS
  • Skip the handling of / in the service worker’s fetch handler
// let the browser handlle the request normally
if (url.pathname === "/") return

Another error

After this, I did some more testing and noticed that when logging in:

  1. I open a fresh, private tab and go to /
  2. This redirects me to /session/new, where I log in
  3. After logging in, /recipes opens and everything seems fine
  4. But if I now manually visit /, the same error happens as before.

Once again the reason was that I also had /recipes in STATIC_ASSETS.

Ensuring redirects are never cached or served

To make sure that I will never cache or return redirected pages from the service worker, I have added a check like !response.redirected at all the locations where i am either (i) saving to cache, or (ii) returning responses from the cache.