Подтвердить что ты не робот

Пытается использовать режим выборки и передачи: 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.. Что мне не хватает?

4b9b3361

Ответ 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, и вы видите эту проблему, вот как я ее решил:

  1. В вашем проекте Laravel выполните команду 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
    

    (В массиве будут другие записи, такие как auth, guest и т.д. Также убедитесь, что вы делаете это в app/Http/kernel.php потому что в Laravel есть и другой kernel.php)

  4. Добавьте это промежуточное ПО при регистрации маршрутов для всех маршрутов, к которым вы хотите разрешить доступ, например:

    Route::group(['middleware' => 'cors'], function () {
        Route::get('getData', 'v1\[email protected]');
        Route::get('getData2', 'v1\[email protected]');
    });
    
  5. В интерфейсе Vue убедитесь, что этот API вызывается в функции mounted() а не в data(). Также убедитесь, что вы используете http:// или https:// с URL в вызове fetch().

Полный список статей в блоге Пита Хьюстона.