mode: 'no-cors' 不会神奇地让事情顺利进行。事实上,它让事情变得更糟,因为它的一个作用是告诉浏览器,“在任何情况下都阻止我的前端 JavaScript 代码查看响应正文和标头的内容。” .
来自前端 JavaScript 的跨域请求的情况是浏览器默认阻止前端代码访问跨域资源。如果Access-Control-Allow-Origin 在响应中,则浏览器会放松该阻止并允许您的代码访问响应。
但如果网站在其响应中未发送 Access-Control-Allow-Origin,您的前端代码将无法直接访问来自该网站的响应。特别是,您无法通过指定 mode: 'no-cors' 来修复它(事实上,这将确保您的前端代码无法访问响应内容)。
但是, 会起作用的一件事是:如果您通过 a CORS proxy 发送请求。
您还可以在 2-3 分钟内轻松地将自己的代理部署到 Heroku,只需 5 个命令:
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
运行这些命令后,您将拥有自己的 CORS Anywhere 服务器,例如,https://cryptic-headland-94862.herokuapp.com/。
在您的请求 URL 前加上您的代理 URL;例如:
https://cryptic-headland-94862.herokuapp.com/https://example.com
将代理 URL 添加为前缀会导致请求通过您的代理发出,其中:
- 将请求转发至
https://example.com。
- 收到来自
https://example.com的回复。
- 将
Access-Control-Allow-Origin 标头添加到响应中。
- 将该响应连同添加的标头一起传递回请求的前端代码。
然后浏览器允许前端代码访问响应,因为带有Access-Control-Allow-Origin 响应标头的响应是浏览器看到的。
即使请求是触发浏览器执行 CORS 预检 OPTIONS 请求的请求,这也有效,因为在这种情况下,代理还会发回使预检成功所需的 Access-Control-Allow-Headers 和 Access-Control-Allow-Methods 标头。
我可以通过 Postman 到达这个端点,http://catfacts-api.appspot.com/api/facts?number=99
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS 解释了为什么即使您可以使用 Postman 访问响应,浏览器也不允许您从 Web 应用程序中运行的前端 JavaScript 代码访问响应跨域,除非响应包含 Access-Control-Allow-Origin响应头。
http://catfacts-api.appspot.com/api/facts?number=99 没有Access-Control-Allow-Origin 响应标头,因此您的前端代码无法跨域访问响应。
您的浏览器可以很好地获得响应,并且您可以在 Postman 甚至浏览器开发工具中看到它——但这并不意味着浏览器会将它暴露给您的代码。他们不会,因为它没有 Access-Control-Allow-Origin 响应头。所以你必须改为使用代理来获取它。
代理向该站点发出请求,获取响应,添加 Access-Control-Allow-Origin 响应标头和所需的任何其他 CORS 标头,然后将其传递回您的请求代码。添加了Access-Control-Allow-Origin 标头的响应是浏览器看到的,因此浏览器允许您的前端代码实际访问响应。
所以我试图将一个对象传递给我的 Fetch,这将禁用 CORS
你不想那样做。需要明确的是,当您说要“禁用 CORS”时,似乎实际上您的意思是要禁用 the same-origin policy。 CORS 本身实际上是一种方法——CORS 是一种放松同源策略的方法,而不是一种限制它的方法。
但无论如何,您确实可以(在您的本地环境中)提供浏览器运行时标志以禁用安全性并以不安全的方式运行,或者您可以在本地安装浏览器扩展程序以绕过同源策略,但所有这样做只是在本地为您改变这种情况。
无论您在本地进行什么更改,尝试使用您的应用的其他人仍然会遇到同源策略,并且您无法为您应用的其他用户禁用该策略。
你很可能永远不想在实践中使用mode: 'no-cors',除非在少数有限的情况下,即使这样,也只有在你确切知道自己在做什么以及效果如何的情况下。这是因为设置 mode: 'no-cors' 实际上对浏览器说的是,“在任何情况下都阻止我的前端 JavaScript 代码查看响应正文和标头的内容。” 在大多数情况下,这显然不是真的你想要什么。
至于您会考虑使用mode: 'no-cors'的情况,请参阅What limitations apply to opaque responses?处的答案以了解详细信息。它的要点是:
-
在有限的情况下,当您使用 JavaScript 将来自另一个来源的内容放入 <script>、<link rel=stylesheet>、<img>、<video>、<audio>、<object>、<embed> 或<iframe> 元素(之所以有效,是因为它们允许跨域嵌入资源)——但由于某种原因,您不想/不能仅仅通过让文档的标记使用资源 URL 作为元素的href 或src 属性。
-
当您只想对资源进行缓存时。正如在 What limitations apply to opaque responses? 中提到的那样,实际上,当您使用 Service Worker 时,相关的 API 就是 Cache Storage API。
但即使在这些有限的情况下,也有一些重要的问题需要注意;请参阅 What limitations apply to opaque responses? 的答案以了解详细信息。
我也试过传入对象{ mode: 'opaque'}
没有mode: 'opaque' 请求模式——opaque 只是响应 的一个属性,浏览器会根据no-cors 模式发送的请求的响应设置该不透明属性。
但顺便说一句,不透明这个词非常明确地表明了您最终得到的响应的性质:“不透明”意味着您看不到它。