从服务工作者发送的 CORS 预检请求,但不是来自常规请求

Posted

技术标签:

【中文标题】从服务工作者发送的 CORS 预检请求,但不是来自常规请求【英文标题】:CORS preflight request sent from service worker, but not from regular request 【发布时间】:2019-01-29 08:58:20 【问题描述】:

我对来自 service worker 的 fetch 请求与来自常规脚本的 fetch 请求之间的区别感到困惑。

我添加了一个服务工作者来拦截由链接到另一个域上的 mp3 的音频元素发出的请求,并且请求失败,因为预检请求不成功。但是,如果我从脚本发出相同的请求,它看起来像是成功的,因为没有发出预检请求。

以下是上述问题的示例故障: https://lucky-marsupial.glitch.me/

这里的代码: https://glitch.com/edit/#!/lucky-marsupial

相关代码摘录如下:

--index.html--
...
<audio src="https://traffic.libsyn.com/thefeed/126_thefeed.mp3?dest-id=149503" crossorigin="anonymous" controls="controls"> Your browser does not support the audio element. </audio>
...

--sw.js--
self.addEventListener('fetch', event => 
  console.log('inside service worker', event.request.url)
  event.respondWith(
    fetch(event.request)
      .then(response => 
        if (response.status === 302) 
          console.log("This line is never reached because preflight failed.")
        
        return response
      )
  )
)

--equivalent fetch request--
fetch("https://traffic.libsyn.com/thefeed/126_thefeed.mp3?dest-id=149503",mode: 'cors')
  .then(response => 
    console.log("This line is reached because no preflight request is sent.")
    return response
  )

您需要重新加载页面以使服务人员生效,然后尝试播放音频,您应该会在控制台中看到错误消息。

【问题讨论】:

您应该提供一个关于您的问题的最小示例(最好是您问题中的代码示例)。 Here is an example - 请在问题中包含代码 - 即 service worker 的代码 - 你可能 做错了™ 抱歉,说得好。我现在已经更新了。忘了我是链接到输出的网站而不是代码本身。 【参考方案1】:

我相信我已经解决了这个问题。我认为由于请求的响应标头将其内容类型设置为text-html,因此它将自动触发预检请求,因为它不是here 列出的内容类型之一。但是,如果在请求中设置了内容类型,则内容类型仅对预检很重要,因此脚本中的获取不需要预检。

但是,Service Worker 中的请求的标头与上面链接中列出的标头范围不同。导致需要预检。添加范围标头或上面链接中未列出的任何标头会导致从脚本中提取以发送预检请求。

有趣的是,当请求来自音频元素本身而不是服务工作者时,它似乎不会触发预检请求,即使您认为它们是同一个请求。

【讨论】:

你能解决这个问题吗?如果是这样,您能发布一下您是如何解决的吗?

以上是关于从服务工作者发送的 CORS 预检请求,但不是来自常规请求的主要内容,如果未能解决你的问题,请参考以下文章

预检时间的 CORS 请求是不是耗时?

骨干同步发送 CORS 预检,但之后啥也不做

由于 CORS 选项预检,ReactJS 无法发送 POST 请求

来自 IE 或 Firefox 的 CORS 请求中没有 Referer 标头

CORS:预检通过,主请求完成 w/200,但浏览器仍然有 Origin 错误

如何处理无效的 CORS 预检请求?