Library Affected: workbox-background-sync
Browser & Platform: all browsers
Issue or Feature Request Description:
The background-sync plugin cannot be used with CORS requests due to the browsers initially sending an OPTIONS request to check the CORS headers.
If the OPTIONS request succeeds but the POST request fails (e.g. 500 error) then the POST request is successfully queued and everything works as expected.
However if we are offline when we first send the request through, the browser sends the OPTIONS request and gets the offline network error. In response the browser never attempts to send the POST request so it doesn't get queued to retry.
Ideally we need some way to store and replay a request chain rather than just a single request so in the instance of a CORS check we can queue the OPTIONS and then the POST request.
I'm not sure what the implementation of this would look like using axios or fetch once implemented.
As it stands the only way to use the background-sync plugin with a remote API is to setup a proxy (E.g. Apache Reverse Proxy or a node proxy) as a subfolder and request to that. However this means we can't for example deploy our PWA on any static file hosts e.g. github pages or an AWS S3 bucket since we cannot add a proxy there.
@jeffposnick This is in regards to our slack conversation where you requested I log a formal bug.
Thanks! CC: @philipwalton for visibility.
Any news on this? Thanks...
No news on this one ? My boi Yanis is crying over this issue right now
Hey all鈥攁pologies for the delay in addressing this.
I'm revisiting it now, and having a hard time even writing a test case that demonstrates the failure. If I do something simple like:
const request = new Request('http://localhost:8002', {
method: 'PUT',
mode: 'cors',
});
const fetchDidFail = ({request}) => console.log('failed: ', request.method),
const networkOnly = new NetworkOnly({plugins: [{fetchDidFail}]});
await networkOnly.handle({request});
and execute that while offline, then what I'm seeing in Chrome and Firefox is that the fetchDidFail callback does get called with the appropriate request value (i.e. corresponding to the original PUT), as opposed to be calling with the OPTIONS or something else that would cause the background sync queue to be confused.
So, taking a step back, does anyone have a small-ish reproduction of the issue, or could explain what they're doing differently in production vs. what that test code is doing?
I got your code to fail just fine as advertised @jeffposnick
I modified it slightly to use post, include a body and set content type.
const request = new Request('https://myRandomDomain.com/home/hello', {
method: 'POST',
mode: 'cors',
headers: new Headers({'content-type': 'application/json'}),
body: JSON.stringify({"name": "name"})
});
const fetchDidFail = ({request}) => console.log('failed: ', request.method);
const networkOnly = new workbox.strategies.NetworkOnly({plugins: [fetchDidFail]});
networkOnly.handle({request}).then(response => console.log("cool "+response.status));
If the server on "myRandomDomain.com" is running it all works fine and it prints "cool 200 (from the last line of code
However, if I stop the webserver running at myRandomDomain.com chrome gives me 2 errors, namely
Access to fetch at 'https://myRandomDomain.com/home/hello' from origin 'https://myDomainRunningMyApp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
And
VM8 workbox-strategies.prod.js:1 Uncaught (in promise) no-response: no-response :: [{"url":"https://myRandomDomain.com/home/hello","error":{}}]
at Object.handle (https://storage.googleapis.com/workbox-cdn/releases/5.1.3/workbox-strategies.prod.js:1:2862)
@rickardliljeberg, my apologies鈥攖he sample I provided was missing {} around {fetchDidFail} (I've since updated it), so it wasn't properly registered as a plugin.
Here's a quick gist with what I just tried: https://gist.github.com/jeffposnick/9f46f36d3ccb39324e47f3433fe881a6
When I run that, I see the fetchDidFail callback invoked with request.method set to POST, and OPTIONS doesn't seem to come into play.
Most helpful comment
Any news on this? Thanks...