Пытается использовать режим выборки и передачи: no-cors
Я могу попасть в эту конечную точку, http://catfacts-api.appspot.com/api/facts?number=99
через Postman и он возвращает JSON
Кроме того, я использую приложение create-react-app и хотел бы избежать настройки любой конфигурации сервера.
В моем клиентском коде я пытаюсь использовать fetch
, чтобы сделать то же самое, но получаю ошибку:
Нет заголовка "Access-Control-Allow-Origin" присутствует в запрошенном ресурс. 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.. Что мне не хватает?
Ответы
Ответ 1
mode: 'no-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>
Ответ 2
Простое решение: добавьте следующее в самый верх php файла, из которого вы запрашиваете данные.
header("Access-Control-Allow-Origin: *");
Ответ 3
Решение для меня было просто сделать это на стороне сервера
Я использовал библиотеку С# 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....
)}
Ответ 4
Очень простое решение (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"
Ответ 5
Поэтому, если вы похожи на меня и разрабатываете веб-сайт на localhost, где вы пытаетесь извлечь данные из Laravel API и использовать их в своем интерфейсе Vue, и вы видите эту проблему, вот как я ее решил:
- В вашем проекте Laravel выполните команду
php artisan make:middleware Cors
. Это создаст app/Http/Middleware/Cors.php
для вас. -
Добавьте следующий код внутри функции handles
в Cors.php
:
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
-
В app/Http/kernel.php
добавьте следующую запись в массив $routeMiddleware
:
‘cors => \App\Http\Middleware\Cors::class
(В массиве будут другие записи, такие как auth
, guest
и т.д. Также убедитесь, что вы делаете это в app/Http/kernel.php
потому что в Laravel есть и другой kernel.php
)
-
Добавьте это промежуточное ПО при регистрации маршрутов для всех маршрутов, к которым вы хотите разрешить доступ, например:
Route::group(['middleware' => 'cors'], function () {
Route::get('getData', 'v1\[email protected]');
Route::get('getData2', 'v1\[email protected]');
});
- В интерфейсе Vue убедитесь, что этот API вызывается в функции
mounted()
а не в data()
. Также убедитесь, что вы используете http://
или https://
с URL в вызове fetch()
.
Полный список статей в блоге Пита Хьюстона.