尝试使用获取和通过模式:无心 [英] Trying to use fetch and pass in mode: no-cors

查看:58
本文介绍了尝试使用获取和通过模式:无心的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以通过邮递员到达此端点 http://catfacts-api.appspot.com/api/facts?number=99 ,它返回 JSON



另外,我正在使用create-react-app,并且希望避免设置任何服务器配置。



在我的客户代码中,我试图使用 fetch 做同样的事情,但是我得到了错误:


所请求的
资源上没有'Access-Control-Allow-Origin'标头。因此,不允许
访问原始地址‘ http:// localhost:3000 。如果不透明的响应满足您的需求,请将请求的
模式设置为 no-cors,以在禁用CORS的情况下获取资源。


所以我试图将一个对象传递到我的Fetch中,这将禁用CORS,例如:

  fetch( 'http://catfacts-api.appspot.com/api/facts?number=99',{模式:'no-cors'})
.then(blob => blob.json())
.then(data => {
console.table(data);
返回数据;
})
.catch(e => {
console.log(e);
return e;
});

有趣的是,我得到的错误实际上是此函数的语法错误。我不确定我的实际获取是否损坏,因为当我删除{mode:'no-cors'}对象,并为其提供不同的URL时,它就可以正常工作



我也尝试传递对象 {模式:'opaque'} ,但这返回了



我相信我需要做的就是禁用CORS。.我缺少什么?

解决方案

模式:'no-cors'不会使事情神奇地起作用。实际上,这会使情况变得更糟,因为它的作用之一就是告诉浏览器, 在任何情况下都禁止我的前端JavaScript代码查看响应正文和标头的内容。 当然,您几乎永远不会


前端JavaScript进行跨域请求会发生什么,默认情况下,浏览器会阻止前端代码访问跨域资源。如果响应中有 Access-Control-Allow-Origin ,则浏览器将放松该阻止并允许您的代码访问响应。


但是,如果站点的响应中没有发送 Access-Control-Allow-Origin ,则您的前端代码将无法直接访问该站点的响应。特别是,您无法通过指定 mode:'no-cors'来解决此问题(事实上,这可以确保您的前端代码可以做到) t访问响应内容)。


但是,将起作用的一件事:如果您通过一个CORS代理 ,例如:


  var proxyUrl ='https://cors-anywhere.herokuapp.com/',
targetUrl ='http:// catfacts-api。 appspot.com/api/facts?number=99'
fetch(proxyUrl + targetUrl)
.then(blob => blob.json())
.then(data => {
console.table(data);
document.querySelector( pre)。innerHTML = JSON.stringify(data,null,2);
返回数据;
} )
.catch(e => {
console.log(e);
return e;
});

 < pre>< ; / pre>  


注意:如果您尝试使用https://cors-anywhere.herokuapp.com,您发现它已关闭,也可以使用5条命令在2-3分钟内轻松地将自己的代理部署到Heroku,

  git克隆https://github.com/Rob--W/cors-anywhere.git 
cd cors-anywhere /
npm install
heroku create
git push heroku master

运行这些命令后,您将拥有自己的命令运行在 https://cryptic-headland-94862.herokuapp.com/。因此,与其在您的请求URL之前添加 https://cors-anywhere.herokuapp.com 前缀,不如在您自己的实例的URL之前添加前缀;例如, https://cryptic-headland-94862.herokuapp.com/https ://example.com





我可以点击此终结点, 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 code>响应标头,因此,您的前端代码无法访问跨域响应。


您的浏览器可以很好地获取响应,并且您可以在Postman甚至浏览器devtools中看到它,但事实并非如此。这并不意味着浏览器会将其公开给您的代码。他们不会,因为它没有 Access-Control-Allow-Origin 响应标头。因此,您必须使用代理来获取它。


代理向该站点发出请求,获取响应,并添加 Access-Control-Allow-Origin 响应标头和所需的任何其他CORS标头,然后将其传递回您的请求代码。浏览器会看到添加了 Access-Control-Allow-Origin 标头的响应,因此浏览器可以让您的前端代码实际访问响应。





所以我试图将一个对象传递到我的Fetch中,这将禁用CORS


您不想这样做。明确地说,当您说要禁用CORS时,您似乎实际上是要禁用同源政策。 CORS本身实际上就是做到这一点的一种方法-CORS是放松同源政策的一种方法,而不是一种限制它的方法。


但是无论如何,您的确可以做到-只是您的本地环境-做一些事情,例如给浏览器运行时标志以禁用安全性并使其运行不安全,或者您可以在本地安装浏览器扩展程序来解决同源策略,但所有操作仅是为您本地改变情况。 / p>

无论您在本地进行什么更改,其他尝试使用您的应用程序的人仍然会遇到同源政策,并且您无法为应用程序的其他用户禁用该功能。


您极有可能永远不想在实践中使用模式:'no-cors',除非少数情况下,即使如此,也只有在您确切知道自己在做什么以及效果如何的情况下,才可以。那是因为设置 mode:'no-cors'对浏览器的实际含义是,阻止我的前端JavaScript代码查看响应主体的内容, 在大多数情况下,这显然不是您想要的。




对于您的情况要考虑使用模式:'no-cors',请参见 对不透明响应有哪些限制? 了解详情。要点是:



  • 在有限的情况下,当您使用JavaScript将来自另一个来源的内容放入< script> < link rel = stylesheet> < img> <视频> <音频> < object> < embed> < iframe> 元素(有效(因为允许跨源嵌入资源),但是由于某些原因,您不想或者不能仅仅通过使文档的标记使用资源URL作为 href src 属性的元素。



  • 何时您要对资源进行的唯一操作就是对其进行缓存。如答案 中提到的那样? ,实际上,适用的情况是您使用Service Workers,在这种情况下,相关的API是缓存存储API




但是即使在那些有限的情况下,也要注意一些重要的陷阱; 请参见 对不透明响应有哪些限制? 了解详情。





我也试图传递对象 {模式:'opaque'}


没有模式:不透明 请求模式-不透明是取而代之的是 response 的属性,浏览器在以 no-cors 模式发送的请求的响应中设置该不透明属性。


但是顺便说一句, opaque 是一个非常明确的信号,表示您最终得到的响应的性质: opaque表示您看不到它。


I can hit this endpoint, http://catfacts-api.appspot.com/api/facts?number=99 via Postman and it returns JSON

Additionally I am using create-react-app and would like to avoid setting up any server config.

In my client code I am trying to use fetch to do the same thing, but I get the error:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

So I am trying to pass in an object, to my Fetch which will disable CORS, like so:

fetch('http://catfacts-api.appspot.com/api/facts?number=99', { mode: 'no-cors'})
  .then(blob => blob.json())
  .then(data => {
    console.table(data);
    return data;
  })
  .catch(e => {
    console.log(e);
    return e;
  });

Interestingly enough the error I get is actually a syntax error with this function. I am not sure my actual fetch is broken, because when I remove the { mode: 'no-cors' } object, and supply it with a different URL it works just fine.

I have also tried to pass in the object { mode: 'opaque'} , but this returns the original error from above.

I belive all I need to do is disable CORS.. What am I missing?

解决方案

mode: 'no-cors' won’t magically make things work. In fact it makes things worse, because one effect it has is to tell browsers, "Block my frontend JavaScript code from looking at contents of the response body and headers under all circumstances." Of course you almost never want that.

What happens with cross-origin requests from frontend JavaScript is that browsers by default block frontend code from accessing resources cross-origin. If Access-Control-Allow-Origin is in a response, then browsers will relax that blocking and allow your code to access the response.

But if a site sends no Access-Control-Allow-Origin in its responses, your frontend code can’t directly access responses from that site. In particular, you can’t fix it by specifying mode: 'no-cors' (in fact that’ll ensure your frontend code can’t access the response contents).

However, one thing that will work: if you send your request through a CORS proxy, like this:

var proxyUrl = 'https://cors-anywhere.herokuapp.com/',
    targetUrl = 'http://catfacts-api.appspot.com/api/facts?number=99'
fetch(proxyUrl + targetUrl)
  .then(blob => blob.json())
  .then(data => {
    console.table(data);
    document.querySelector("pre").innerHTML = JSON.stringify(data, null, 2);
    return data;
  })
  .catch(e => {
    console.log(e);
    return e;
  });

<pre></pre>

Note: if when you go to try to use https://cors-anywhere.herokuapp.com, you find it’s down, you can also easily deploy your own proxy to Heroku in literally just 2-3 minutes, with 5 commands:

git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master

After running those commands, you’ll end up with your own CORS Anywhere server running at, e.g., https://cryptic-headland-94862.herokuapp.com/. So then rather than prefixing your request URL with https://cors-anywhere.herokuapp.com, prefix it instead with the URL for your own instance; e.g., https://cryptic-headland-94862.herokuapp.com/https://example.com.


I can hit this endpoint, http://catfacts-api.appspot.com/api/facts?number=99 via Postman

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS explains why it is that even though you can access the response with Postman, browsers won’t let you access the response cross-origin from frontend JavaScript code running in a web app unless the response includes an Access-Control-Allow-Origin response header.

http://catfacts-api.appspot.com/api/facts?number=99 has no Access-Control-Allow-Origin response header, so there’s no way your frontend code can access the response cross-origin.

Your browser can get the response fine and you can see it in Postman and even in browser devtools—but that doesn’t mean browsers will expose it to your code. They won’t, because it has no Access-Control-Allow-Origin response header. So you must instead use a proxy to get it.

The proxy makes the request to that site, gets the response, adds the Access-Control-Allow-Origin response header and any other CORS headers needed, then passes that back to your requesting code. And that response with the Access-Control-Allow-Origin header added is what the browser sees, so the browser lets your frontend code actually access the response.


So I am trying to pass in an object, to my Fetch which will disable CORS

You don’t want to do that. To be clear, when you say you want to "disable CORS" it seems you actually mean you want to disable the same-origin policy. CORS itself is actually a way to do that — CORS is a way to loosen the same-origin policy, not a way to restrict it.

But anyway, it’s true you can — in just your local environment — do things like give your browser runtime flags to disable security and run insecurely, or you can install a browser extension locally to get around the same-origin policy, but all that does is change the situation just for you locally.

No matter what you change locally, anybody else trying to use your app is still going to run into the same-origin policy, and there’s no way you can disable that for other users of your app.

You most likely never want to use mode: 'no-cors' in practice except in a few limited cases, and even then only if you know exactly what you’re doing and what the effects are. That’s because what setting mode: 'no-cors' actually says to the browser is, "Block my frontend JavaScript code from looking into the contents of the response body and headers under all circumstances." In most cases that’s obviously really not what you want.


As far as the cases when you would want to consider using mode: 'no-cors', see the answer at What limitations apply to opaque responses? for the details. The gist of it is that the cases are:

  • 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 or 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 the answer What limitations apply to opaque responses?, in practice the scenario that applies to is when you’re using Service Workers, in which case the API that’s relevant is the Cache Storage API.

But even in those limited cases, there are some important gotchas to be aware of; see the answer at What limitations apply to opaque responses? for the details.


I have also tried to pass in the object { mode: 'opaque'}

There is no mode: 'opaque' request mode — opaque is instead just a property of the response, and browsers set that opaque property on responses from requests sent with the no-cors mode.

But incidentally the word opaque is a pretty explicit signal about the nature of the response you end up with: "opaque" means you can’t see it.

这篇关于尝试使用获取和通过模式:无心的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆