Hi, not sure if this is right place for this, but figured it's a good place to start. I read through the discussions on:
https://github.com/whatwg/fetch/issues/66
https://github.com/slightlyoff/ServiceWorker/issues/607
https://github.com/slightlyoff/ServiceWorker/issues/119
https://github.com/slightlyoff/ServiceWorker/issues/757
But even after reading all of that, I'm not sure how to implement/fix my service worker to handle redirects to login pages. My use case is very similar to bhritchie@ (https://github.com/slightlyoff/ServiceWorker/issues/607#issuecomment-118093909)
1- I have an app for which I'm caching the app shell in my SW running under /app
2- If the user hits that end point, but they are not logged in, they get redirected to /login
3- login is via POST, with json returned on success. The client JS then attempts to reload /app (eg, effectively: window.location = response.originalUrl);
To keep my app as snappy as possible, I'm trying to use a cache first strategy. (To be more accurate I'm using a Promise.race, so really it's a 'fastest' strategy, but that results in the same thing practically).
The problem is obviously that the result of step 2 is cached. So when the the client tries to reload /app they end up back on the login page, rather than seeing the actual app.
I noticed sw-toolbox checks the response status before caching it; eg:
var successResponses = /^0|([123]\d\d)|(40[14567])|410$/;
successResponses.test(response.status) --> then cache
I do something similar and figured I would just not cache the response if it's a 302. But clearly that doesn't work, because I dont actually see the 302 in my fetch response, since it's a opaquaredirect handled by the browser. Indeed, debugging this, I noticed my SW only ever sees 200 or 0 (it uses fetch), but never a 302.
The linked bugs talk about manual redirects, and event.default(), but it's all a lot of discussion and i'm lost through the trees. Can the SW handle redirects and decide what to cache / ignore? Or do I need to jump through hoops to compare request.url to response.url and not cache the response if they dont match?
Perhaps it would be helpful to have examples for authenticated PWA apps? All other examples are great and useful, but maybe not overly practical. Most examples talk about not using production quality caching strategies, something which is left as an exercise for the reader.
PS. I appreciate caching authenticated resources is a bit of a can of worms. I suspect I'll need to clear the cache on logout. And similarly (in case the user logout via a different tab/browser/whatever without my SW getting involved, then I probably also need to clear the cache on any 401 / 403...
But whilst it's a can of worms, surely it's a common practice? Short of calculators and weather apps, most apps require you to log in? So too should an offline PWA be able to handle this easily?
PPS. I'm running on Mac 50.0.2661.102 (Official Build) (64-bit) and it seems like the dev console often gets it's knickers in a twist wrt requests. Having the console show all sorts of errors, that didn't happen afaict nor that show up in the network tab. It even starts to log errors when I'm editing the omnibox without actually making it refresh/load anything. Are there known bugs here, or shall I try and repro these cases and raise them (separately somewhere else)? I also find if I leave my laptop for a bit, the tab showing my app has it's devconsole hung... completely unresponsive and I need to kill the tab and open a new one... ?
FWIW, if you want access to the contents of a redirect that is a feature I think is worth considering and adding to Fetch eventually. It'll require a new opt-in header, but should be relatively straightforward. There just hasn't really been much demand for it thus far.
To keep my app as snappy as possible, I'm trying to use a cache first strategy. (To be more accurate I'm using a Promise.race, so really it's a 'fastest' strategy, but that results in the same thing practically).
You need to be careful with this. Promise.race takes the first settled state, so a rejecting promise will "beat" a fulfilling one. See https://jakearchibald.com/2014/offline-cookbook/#cache-network-race for a better race implementation.
I do something similar and figured I would just not cache the response if it's a 302. But clearly that doesn't work, because I dont actually see the 302 in my fetch response, since it's a opaquaredirect
You could check for response.type == 'opaqueredirect'.
The linked bugs talk about manual redirects, and event.default()
event.default() is dead, we don't need it anymore.
Can the SW handle redirects and decide what to cache / ignore?
cache.addAll won't cache !ok responses, but it will cache redirects. With cache.put you can cache whatever you want.
Most examples talk about not using production quality caching strategies, something which is left as an exercise for the reader.
What do you mean by this? Does https://jakearchibald.com/2016/caching-best-practices/ help?
I appreciate caching authenticated resources is a bit of a can of worms. I suspect I'll need to clear the cache on logout. And similarly (in case the user logout via a different tab/browser/whatever without my SW getting involved
Or key your cache names (and other storage) on the user name. That way you can support multiple logged in users. Of course, if the expectation is that data should be cleared on logout, you should clear data. https://w3c.github.io/webappsec-clear-site-data/ is being developed for this.
PPS. I'm running on Mac 50.0.2661.102 (Official Build) (64-bit) and it seems like the dev console often gets it's knickers in a twist wrt requests.
Chrome bugs can be reported at crbug.com, but check in Canary first. If they've already been fixed, no need to report them.
Closing this as it seems more of a support request than a feature request, but I'll continue to reply here and provide support.
If it turns out we need a new fetch feature for this, we'll create one in the fetch repo.
I am also facing same kinda issue. I am using PWA in my angular 5 application, which also uses angular-cli and keycloak for login. Here if I go offline application tries to hit the keycloak server to get the login information. And during this operation app redirects to keycloak URL for authentication and fails due to network connection. Please let me know how do I handle it. Let me know if you need some more info.
I do think we need some more recommendations / cookbooks around SW caching and authenticated experiences.
I.e. things like
caches API.Authorization headers with tokens will be persisted in cache unless developer takes action to delete that header before caching@jakearchibald Couldn't find any repo regarding this request.
Most helpful comment
I do think we need some more recommendations / cookbooks around SW caching and authenticated experiences.
I.e. things like
cachesAPI.-- That means
Authorizationheaders with tokens will be persisted in cache unless developer takes action to delete that header before caching