简体   繁体   中英

How do I handle non-CORS polluted browser cache resulting from AWS s3, with my Service Worker?

My company has many applications that request shared resources that live on AWS S3. Some of those applications use the crossorigin="anonymous" html element, and some do not. AWS does not send back CORS response headers, like 'Allow-access-control-origin,' when there is no Origin request header . As a result, some users can wind up with a broswer cache version of a file that has no CORS response headers.

When those users come to my team's application, Service Worker can fail to request those shared assets because the browser disk cache has them in a non-cors fashion. The error looks like this:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin ' http://localhost:8001 ' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Of course I cannot use an opaque response for reliable caching.

I figured I could apply a cache-control request header to bypass the browser cache, but the Headers object of the Fetch API Request is immutable . So, I cannot add headers to the existing request. If I try to make a new Request, I cannot get a CORS response back from AWS, because Origin is a forbidden header that I cannot set in the Fetch API.

This problem would be solved if:

  • I could enforce all the teams in my company to make sure they use the crossorigin html attribute, but I cannot.

  • I could make AWS always respond with CORS headers, but I cannot.

  • make a Fetch Request with and Origin header, but I cannot.

  • convince my organization to set cache-control headers that disallowed browser caching of assets, but that's a bad idea.

Is there anything I can do to overcome this? Right now, I am just disabling Service Worker caching on these shared assets, to avoid network failures.

You say your problem would be solved if you could make a Fetch Request with an Origin header, but I cannot.

You should be able to do that by constructing your own Request and explicitly setting the mode to 'cors' . Here's an example:

 const failingRequest = new Request('https://example.com', { mode: 'cors' }); fetch(failingRequest).then(console.log).catch(console.warn); const successfulRequest = new Request('https://cors-test.appspot.com/test', { mode: 'cors' }); fetch(successfulRequest).then(console.log).catch(console.warn); 

You should see that CORS-enabled requests are made to both https://example.com and https://cors-test.appspot.com/test . The first request will fail because the server doesn't support CORS, while the second will succeed and resolve with a non-opaque Response object.

Looks like we want more control over how caching is handled by our service worker like the new cache option shipping in Firefox detailed here: https://hacks.mozilla.org/2016/03/referrer-and-cache-control-apis-for-fetch/ It's an existing Chromium issue to implement here https://bugs.chromium.org/p/chromium/issues/detail?id=453190

Ideally we would do something like this:

  // Download a resource with cache busting, to bypass the cache
  // completely.
  fetch("some.json", {cache: "no-store"}) // or "reload"
    .then(function(response) { /* consume the response */ });

I guess I will just have my application request all of these shared assets with a query string that is specific to my application. Feels wrong, but should work.

EDIT - Thanks to Jeff, I don't have to do browser cache busting. I can just always go over the network when the service worker needs an asset. This is what I am doing, and it works to make a CORS request that avoids the browser disk cache:

function respondWithCacheOrNetwork(event) {
  var headers = new Headers();
  event.request.headers.forEach((v, k) => { headers.set(k, v); });
  // Copy the old headers, cannot modify because immutable
  headers.set('cache-control', 'no-cache');
  var skipBrowserCacheRequest = new Request(event.request.url,
    {
      mode: 'cors',
      method: event.request.method,
      headers: headers
    }
  );
    event.respondWith(toolbox.cacheFirst(skipBrowserCacheRequest));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM