我可以通过Postman点击这个端点http://catfacts-api.appspot.com/api/facts?number=99,它返回JSON
此外,我正在使用创建-反应-应用程序,并希望避免设置任何服务器配置。
在我的客户端代码中,我试图使用fetch来做同样的事情,但我得到了错误:
被请求对象上没有'Access-Control-Allow-Origin'报头
资源。因此,来源“http://localhost:3000”是不允许的
访问。如果不透明响应满足您的需求,请设置请求的
mode为'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;
});
有趣的是,我得到的错误实际上是这个函数的语法错误。我不确定我的实际获取是坏的,因为当我删除{mode: 'no-cors'}对象,并提供了一个不同的URL,它工作得很好。
我还尝试过传入object {mode: 'opaque'},但这将从上面返回原始错误。
我相信我所需要做的就是禁用CORS..我错过了什么?
我的解决方案是在服务器端进行
我使用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获取调用就像这样简单:
//React component
fetch(`api/ItemImage/GetItemImageFromURL?url=${imageURL}`, {
method: 'GET',
})
.then(resp => resp.json() as Promise<ItemImage>)
.then(imgResponse => {
// Do more stuff....
)}
所以如果你像我一样,在localhost上开发一个网站,你试图从Laravel API获取数据,并在你的Vue前端使用它,你看到了这个问题,这是我如何解决它:
In your Laravel project, run command php artisan make:middleware Cors. This will create app/Http/Middleware/Cors.php for you.
Add the following code inside the handles function in Cors.php:
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
In app/Http/kernel.php, add the following entry in $routeMiddleware array:
‘cors’ => \App\Http\Middleware\Cors::class
(There would be other entries in the array like auth, guest etc. Also make sure you're doing this in app/Http/kernel.php because there is another kernel.php too in Laravel)
Add this middleware on route registration for all the routes where you want to allow access, like this:
Route::group(['middleware' => 'cors'], function () {
Route::get('getData', 'v1\MyController@getData');
Route::get('getData2', 'v1\MyController@getData2');
});
In Vue front-end, make sure you call this API in mounted() function and not in data(). Also make sure you use http:// or https:// with the URL in your fetch() call.
Pete Houston的博客文章。