服务人员发送的CORS飞行前请求,但不是常规请求

时间:2018-08-23 03:41:10

标签: javascript cors fetch service-worker preflight

对于服务工作者的获取请求与常规脚本的获取请求之间的区别,我感到困惑。

我添加了一个服务人员,以拦截音频元素发出的请求,该音频元素链接到另一个域上的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
  })

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

1 个答案:

答案 0 :(得分:1)

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

但是,服务工作者中的请求具有一个标头,而不是上面链接范围中列出的标头。导致需要进行飞行前检查。添加范围标头或上面链接中未列出的任何标头,都会导致从脚本中获取内容以发送预检请求。

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