模式:“no-cors”不会神奇地让事情起作用。事实上,它使事情变得更糟,因为它的一个效果是告诉浏览器,“在任何情况下都阻止我的前端JavaScript代码看到响应体和报头的内容。”当然你永远都不想那样。
来自前端JavaScript的跨源请求是浏览器默认阻止前端代码访问跨源资源。如果在响应中有access - control - allow - origin,那么浏览器会放松阻塞,并允许您的代码访问响应。
但是如果一个站点在它的响应中没有发送access - control - allow - origin,你的前端代码就不能直接访问该站点的响应。特别是,你不能通过指定mode: 'no-cors'来修复它(事实上,这将确保你的前端代码不能访问响应内容)。
然而,有一件事是可行的:如果你通过CORS代理发送请求。
您还可以轻松地部署自己的代理到Heroku,只需2-3分钟,只需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 preflight OPTIONS请求的请求,这也可以工作,因为在这种情况下,代理还会发回使preflight成功所需的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甚至在浏览器devtools中看到它,但这并不意味着浏览器将它暴露给您的代码。它们不会,因为它没有Access-Control-Allow-Origin响应头。因此,您必须使用代理来获取它。
代理向该站点发出请求,获得响应,添加Access-Control-Allow-Origin响应标头和所需的任何其他CORS标头,然后将其传递回请求代码。加上access - control - allow - origin头的响应是浏览器看到的,所以浏览器让前端代码实际访问响应。
我试图传递一个对象给Fetch,它会禁用CORS
你不会想这么做的。需要明确的是,当您说要“禁用CORS”时,似乎实际上是指要禁用同源策略。CORS本身实际上是一种实现这一目标的方式——CORS是一种放松同源政策的方式,而不是一种限制政策的方式。
但无论如何,确实可以在本地环境中设置浏览器运行时标志来禁用安全性并不安全地运行,或者可以在本地安装浏览器扩展来绕过同源策略,但所有这些都只是在本地改变了情况。
无论你在本地做了什么改变,任何试图使用你的应用的人仍然会遇到同源策略,你没有办法为你的应用的其他用户禁用它。
你很可能永远都不想在实践中使用mode: 'no-cors',除非在一些有限的情况下,即使在这种情况下,你也只知道你在做什么以及效果是什么。这是因为设置模式:'no-cors'实际上对浏览器说的是,“在任何情况下都阻止我的前端JavaScript代码查看响应体和报头的内容。”在大多数情况下,这显然不是你想要的。
至于你想要考虑使用mode: 'no-cors'的情况,请参阅What limits apply to opaque responses?详情如下。它的要点是:
In the limited case when you’re using JavaScript to put content from another origin into a <script>, <link rel=stylesheet>, <img>, <video>, <audio>, <object>, <embed>, or <iframe> element (which works because embedding of resources cross-origin is allowed for those)—but for some reason you don’t want to/can’t do that just by having the markup of the document use the resource URL as the href or src attribute for the element.
When the only thing you want to do with a resource is to cache it. As alluded to in What limitations apply to opaque responses?, in practice the scenario that’s for is when you’re using Service Workers, in which case the API that’s relevant is the Cache Storage API.
但即使在这些有限的情况下,也有一些重要的陷阱需要注意;看答案在什么限制适用于不透明的回应?详情如下。
我还尝试过传入对象{mode: 'opaque'}
不存在“opaque”请求模式——opaque只是响应的一个属性,浏览器会在以no-cors模式发送的请求的响应上设置该opaque属性。
但顺便提一下,“opaque”这个词是一个非常明确的信号,表明了你最终得到的回答的性质:“opaque”意味着你看不到它的任何细节;它挡住了你的视线。