【问题标题】:How do I handle non-CORS polluted browser cache resulting from AWS s3, with my Service Worker?如何使用我的 Service Worker 处理由 AWS s3 产生的非 CORS 污染的浏览器缓存?
【发布时间】:2017-04-29 04:27:46
【问题描述】:

我的公司有许多应用程序请求 AWS S3 上的共享资源。其中一些应用程序使用crossorigin="anonymous" html 元素,而另一些则不使用。 AWS 不会发回 CORS 响应标头,例如“Allow-access-control-origin”when there is no Origin request header。因此,一些用户可能会使用没有 CORS 响应标头的文件的浏览器缓存版本。

当这些用户访问我团队的应用程序时,Service Worker 可能无法请求这些共享资产,因为浏览器磁盘缓存以非 cors 方式拥有它们。错误如下所示:

请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'http://localhost:8001' 不允许访问。如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源。

当然,我不能使用不透明的响应来进行可靠的缓存。

我想我可以应用缓存控制请求标头来绕过浏览器缓存,但 Fetch API Request is immutable 的 Headers 对象。因此,我无法向现有请求添加标头。如果我尝试发出新请求,我无法从 AWS 获得 CORS 响应,因为我无法在 Fetch API 中设置 Origin is a forbidden header

如果满足以下条件,此问题将得到解决:

  • 我可以强制公司中的所有团队确保他们使用跨域 html 属性,但我不能。

  • 我可以让 AWS 始终使用 CORS 标头进行响应,但我不能。

  • 使用 Origin 标头发出 Fetch Request,但我不能。

  • 说服我的组织设置缓存控制标头,禁止浏览器缓存资产,但这是个坏主意。

我能做些什么来克服这个问题吗?现在,我只是在这些共享资产上禁用 Service Worker 缓存,以避免网络故障。

【问题讨论】:

  • Allow-access-control-origin - 你的意思是Access-Control-Allow-Origin 吗?
  • the Headers object of the Fetch API Request is immutable 在非常特殊的情况下 - 我不明白为什么你不应该设置请求标头
  • Origin is a forbidden header that I cannot set in the Fetch API - 浏览器控制 Origin 标头,为什么需要更改它?
  • 是的,我的意思是访问控制允许来源。

标签: javascript amazon-s3 cors service-worker


【解决方案1】:

我想我会让我的应用程序使用特定于我的应用程序的查询字符串请求所有这些共享资产。感觉不对,但应该可以。

编辑 - 感谢 Jeff,我不必进行浏览器缓存破坏。当服务人员需要资产时,我总是可以通过网络。这就是我正在做的事情,它可以发出一个避免浏览器磁盘缓存的 CORS 请求:

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));
}

【讨论】:

    【解决方案2】:

    你说如果你可以使用 Origin 标头发出 Fetch Request,你的问题就会得到解决,但我不能。

    您应该能够通过构建自己的Request 并将mode 显式设置为'cors' 来做到这一点。这是一个例子:

    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);

    您应该看到启用了 CORS 的请求同时发送到 https://example.comhttps://cors-test.appspot.com/test。第一个请求将失败,因为服务器不支持 CORS,而第二个请求将成功并使用不透明的 Response 对象进行解析。

    【讨论】:

    • 你知道吗,你是对的。我因此自欺欺人:var r = new Request('https://my.server/cors-file.thing', {mode: 'cors'}); undefined r.headers.keys().next(); Object {done: true, value: undefined} 我猜 Origin 标头是在 fetch 发出后添加的?
    • 我认为一般的想法是你说你想要一个 CORS 请求,然后浏览器会为你计算出所有的细节,就像你在另一个上下文中发出一个 CORS 请求一样。
    【解决方案3】:

    看起来我们希望更好地控制我们的服务工作者如何处理缓存,例如 Firefox 中提供的新缓存选项,详细信息如下:https://hacks.mozilla.org/2016/03/referrer-and-cache-control-apis-for-fetch/ 这是一个现有的 Chromium 问题,可以在这里实现https://bugs.chromium.org/p/chromium/issues/detail?id=453190

    理想情况下,我们会这样做:

      // 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 */ });
    

    【讨论】:

    • 是的,那很好,这样我就不必与标题周围的保护作斗争了。
    猜你喜欢
    • 2017-05-11
    • 2019-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 2011-09-14
    • 2017-09-09
    • 2016-07-22
    相关资源
    最近更新 更多