尝试使用获取和通过模式:无心

2020/10/21 23:22 · javascript ·  · 0评论

我可以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', { mode: 'no-cors'})
  .then(blob => blob.json())
  .then(data => {
    console.table(data);
    return data;
  })
  .catch(e => {
    console.log(e);
    return e;
  });

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

我也尝试传递对象{ mode: 'opaque'},但这会从上面返回原始错误。

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

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

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

但是,如果站点Access-Control-Allow-Origin在响应中未发送任何信息,则您的前端代码将无法直接从该站点访问响应。特别是,您无法通过指定进行修复mode: 'no-cors'(实际上,这将确保您的前端代码无法访问响应内容)。

但是,这起作用:如果您通过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);
    return data;
  })
  .catch(e => {
    console.log(e);
    return e;
  });
<pre></pre>

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

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前面加上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/zh-CN/docs/Web/HTTP/Access_control_CORS解释了为什么即使您可以使用Postman访问响应,浏览器也不允许您从前端跨源访问响应除非响应中包含Access-Control-Allow-Origin响应标头,否则Web应用程序中将运行JavaScript代码

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'除了极少数情况下您极有可能永远不想在实践中使用,甚至只有在您确切知道自己在做什么和产生什么影响的情况下才可以在实践中使用它。这是因为设置mode: 'no-cors'实际上对浏览器的含义是:“在任何情况下都禁止我的前端JavaScript代码查看响应正文和标头的内容。” 在大多数情况下,这显然不是您想要的。


至于情况下,您考虑使用mode: 'no-cors',请在答案限制适用于不透明的反应是什么?有关详细信息。其要点是:

  • 在你使用JavaScript的时候把内容从另一个起源到有限的情况下<script><link rel=stylesheet><img><video><audio><object><embed>,或<iframe>元素(它的作品,因为资源的嵌入跨域允许那些) -但由于某种原因,你不”仅仅通过让文档的标记使用资源URL作为元素hreforsrc属性,就可以做到这一点

  • 当您只想对资源进行缓存时。正如答案中提到的那样,对不透明响应有哪些限制?,实际上,适用的情况是使用Service Workers时,在这种情况下,相关的API是Cache Storage API

但是即使在那些有限的情况下,也要注意一些重要的陷阱。请参见以下答案:不透明响应有哪些限制?有关详细信息。


我也尝试过传递对象 { mode: 'opaque'}

没有mode: 'opaque'请求模式-opaque而是仅是response的属性,浏览器在以该no-cors模式发送的请求的响应上设置了该不透明属性

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

因此,如果您像我一样,并且在localhost上开发一个网站,尝试从Laravel API中获取数据并在Vue前端中使用它,那么您会看到此问题,这是我如何解决的问题:

  1. 在您的Laravel项目中,运行command php artisan make:middleware Cors这将为app/Http/Middleware/Cors.php创建
  2. handles函数中的以下代码中添加以下代码Cors.php

    return $next($request)
        ->header('Access-Control-Allow-Origin', '*')
        ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
    
  3. 在中app/Http/kernel.php,在$routeMiddleware数组中添加以下条目

    ‘cors’ => \App\Http\Middleware\Cors::class
    

    (数组中还会有其他条目,例如authguest等等。还要确保您正在执行此操作,app/Http/kernel.php因为kernel.phpLaravel中也有另一个条目)

  4. 在要允许访问的所有路由的路由注册中添加此中间件,如下所示:

    Route::group(['middleware' => 'cors'], function () {
        Route::get('getData', 'v1\MyController@getData');
        Route::get('getData2', 'v1\MyController@getData2');
    });
    
  5. 在Vue前端中,请确保您在mounted()函数而不是中调用此API data()另外,请确保您使用http://https://fetch()呼叫中使用URL

完全归功于Pete Houston的博客文章

简单的解决方案:将以下内容添加到您要从中请求数据的php文件的顶部。

header("Access-Control-Allow-Origin: *");

我的解决方案是只在服务器端执行此操作

我使用C#WebClient库获取数据(在我的情况下是图像数据)并将其发送回客户端。您选择的服务器端语言可能存在一些非常相似的东西。

//Server side, api controller

[Route("api/ItemImage/GetItemImageFromURL")]
public IActionResult GetItemImageFromURL([FromQuery] string url)
{
    ItemImage image = new ItemImage();

    using(WebClient client = new WebClient()){

        image.Bytes = client.DownloadData(url);

        return Ok(image);
    }
}

您可以将其调整为自己的用例。client.DownloadData()工作要点没有任何CORS错误。通常,CORS问题仅发生在网站之间,因此可以从您的服务器发出“跨站点”请求。

然后,React fetch调用非常简单:

//React component

fetch(`api/ItemImage/GetItemImageFromURL?url=${imageURL}`, {            
        method: 'GET',
    })
    .then(resp => resp.json() as Promise<ItemImage>)
    .then(imgResponse => {

       // Do more stuff....
    )}

如果您使用Express作为后端,则只需安装cors并将其导入并在app.use(cors());中使用。如果仍无法解决,请尝试切换端口。切换端口后肯定会解决

一个非常简单的解决方案(配置需要2分钟)是使用来自以下位置的local-ssl-proxy软件包:npm

用法很简单:

1.安装软件包:
npm install -g local-ssl-proxy

2.在运行
local-server面罩时,使用local-ssl-proxy --source 9001 --target 9000

PS:更换--target 9000-- "number of your port"--source 9001--source "number of your port +1"

本文地址:http://javascript.askforanswer.com/changshishiyonghuoquhetongguomoshiwuxin.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!