Safari:重新加载后“由于访问控制检查而无法加载 Fetch API”

Posted

技术标签:

【中文标题】Safari:重新加载后“由于访问控制检查而无法加载 Fetch API”【英文标题】:Safari: "Fetch API cannot load due to access control checks" after reload 【发布时间】:2020-11-18 07:49:53 【问题描述】:

我在 Safari 的 CORS 系统中遇到了一些奇怪的行为。 我有一个从 JS Fetch API 发送的 POST 请求,如下所示:

const res = await fetch('http://localhost:8888/myPath', 
  method: 'POST',
  mode: 'cors',
  headers: 
    'Content-Type': 'application/json'
  ,
  body: JSON.stringify(body)
);

根据 Safari 的网络监视器,请求头是这样的:

POST /myPath HTTP/1.1
Accept: */*
Content-Type: application/json
Origin: http://my.domain.com
Content-Length: 335
Accept-Language: en-gb
Host: localhost:8888
User-Agent: Mozilla/5.0...
Referer: http://my.domain.com
Accept-Encoding: gzip, deflate
Connection: keep-alive

以下响应来自服务器:

HTTP/1.1 200 OK
Date: Tue, 28 Jul 2020 19:15:45 GMT
Vary: Origin
Content-Length: 4
Content-Type: application/json
Access-Control-Allow-Origin: http://my.domain.com
Server: uvicorn

很遗憾,我的这台机器上没有 Wireshark,而且 Safari 也没有显示预检请求。所以我不知道是否发生了预检以及情况如何。

现在的问题是:当我有一个新的浏览器会话(例如使用私有模式)并访问我的触发获取请求的文档时,一切正常。 只有在重新加载页面以再次发送 CORS 请求后,我才会在 Safari 控制台中收到“由于访问控制检查而无法加载 Fetch API”。 所以我想,这与 Safari 如何缓存 CORS 请求/预检有关。

在 Firefox 和 Chrome 中,我的 CORS 请求非常有效。

我该如何解决这个问题?

【问题讨论】:

我也有同样的问题。我无法确定这是 Safari 缓存错误,还是可以通过服务器上的 CORSrule 修复的问题。仅当 Safari 对 缓存的 资源进行预检 CORS 检查时才会发生这种情况,这一事实让我认为它是 Safari。 除了终止正斜杠的建议外,这篇文章还建议在所有支持 CORS 的响应中添加以下标头:Vary: Origin, Access-Control-Request-Headers, Access-Control-请求方法***.com/questions/44800431/… 问题可能是由于这个“错误”/对标准的无知吗? bugs.webkit.org/show_bug.cgi?id=171934 【参考方案1】:

如果您可以控制您的服务器,我的建议是在您的“http://localhost:8888/myPath/”上添加一个终止正斜杠。

例如:

const res = await fetch('http://localhost:8888/myPath/', 
  method: 'POST',
  mode: 'cors',
  headers: 
    'Content-Type': 'application/json'
  ,
  body: JSON.stringify(body)
);

背景

我建议这样做的原因是我有完全相同的问题。我对这个问题的看法是,它表现为 Safari 未能对缓存图像进行预检 CORS 检查,其中图像 src 是重定向(Canvas Instructure URL 重定向到 AWS S3 存储桶)。以您的示例为例,我怀疑它与您的 localhost 与 domain.com 主机名变体有关。

我的 Safari 控制台错误是主机页面的主机域被图像来源的域拒绝。我希望您的情况与此类似。

FetchEvent.respondWith received an error:
TypeError: Cross-origin redirection to <actual image source> 
denied by Cross-Origin Resource Sharing policy: 
Origin <hosted page containing the image src redirect to image source> 
is not allowed by Access-Control-Allow-Origin. 

原始的 CORS 请求很好。只有对 缓存资源 的预检检查失败。我希望这是一个 Safari 错误,因为如果它是一项功能,Chrome 和 Firefox 可能会出现奇怪的行为。

复制我对同一问题的变体:

    在 Safari(带有文件缓存的 v13.2、桌面或 ios)中,转到站点 https://cidilabs.instructure.com/courses/3/pages/upload-slash-embed-image-test。我无法控制这个公共页面,如果它变成一个损坏的链接,我深表歉意。如果您有权访问 Canvas LMS,则可以通过 Canvas 图像上传工具将图像上传到模块页面来复制此页面。 Canvas 将上传的图片作为重定向链接嵌入到 S3 存储桶。 然后刷新该页面,对缓存图像发起预检 CORS 请求,以查看损坏的图像链接。

解决方法选项:

在使用嵌入了 CORS 重定向图像的页面时,始终打开专用浏览器。该问题仅在缓存图像时发生。 [对用户来说不是一个实用的解决方案] 为所有作为 CORS 重定向路径的可缓存资源添加一个终止符(正斜杠)。仅当重定向路径看起来像文件而不是目录时才会出现此问题。 [对于图像 src URL 的这种不好的风格,我感到很痛苦。但是,因为图像 src 实际上是重定向而不是真正的文件,所以我认为将其显示为 dir 也不错。] ** 最实用的坏解决方法 使图像 src URL 成为与其嵌入的页面不同的主机。仅当缓存的图像 src 重定向 URL 与网页的主机相同时,才会出现此问题。 【这太奇怪了!也许,Safari 以某种疯狂的方式缓存主机页面资源。] 在转到带有 CORS 图像 src 重定向的页面时使用 FireFox 或 Chrome。该问题仅发生在 Safari 上。 [糟糕的解决方法,切断了很多用户]

【讨论】:

您找到合适的解决方案了吗?我遇到了一个类似的问题,iOS Safari(迄今为止我唯一遇到问题的浏览器)为使用crossorigin="anonymous" 检索的缓存图像抛出Origin &lt;url&gt; is not allowed by Access-Control-Allow-Origin 错误。令人沮丧的部分是这种情况并非一直发生,哪些图像引发错误似乎是随机的。我正在使用 DigitalOcean Spaces,它本质上是用于云存储的 AWS S3 克隆。我只将 AllowedMethod 设置为 GETHEAD 用于 cors 规则并将我的主机列入白名单。【参考方案2】:

对我来说,是 Adblocker 打破了这一点。我有一个名为“advertiser_id”的查询参数,我的 Adblocker 将其识别为“需要被阻止”。导致问题描述的cors错误。

只需禁用广告拦截器即可解决问题。

【讨论】:

以上是关于Safari:重新加载后“由于访问控制检查而无法加载 Fetch API”的主要内容,如果未能解决你的问题,请参考以下文章

Safari 重新加载内存中的视频

内容仅在重新加载后显示

在 Safari 中为网站重新加载 javascript 和 css 文件

iPhone Web App Div 标签在 Safari 中重新加载

iOS safari 崩溃(问题反复出现)

设置隐藏的下拉选择值会导致 iOS 11 Safari 中的页面重新加载