Ответ на предполетный запрос не проходит ошибка проверки контроля доступа

Точная ошибка, с которой я борюсь: «Ответ на предварительный запрос не проходит проверку контроля доступа: на запрошенном ресурсе нет заголовка Access-Control-Allow-Origin. Следовательно, Origin 'null' не разрешен доступ. ".

Я пытаюсь получить данные JSON с помощью JavaScript из https://api.kraken.com/0/public/OHLC?pair=ETHEUR. Для этого я создал объект XMLHttpRequest и указал GET в качестве типа запроса. Предположительно это простой запрос, однако в сообщении об ошибке написано, что предполетный запрос был отправлен. В чем причина такого поведения? При этом, чтобы исправить эту ошибку, я попытался установить заголовок запроса, в котором я указал «*» в качестве значения для Access-Control-Allow-Origin, но все равно получаю сообщение об ошибке. Я просмотрел ответы на похожие вопросы, но не смог понять, как решить проблему, с которой имею дело. Вероятно, это связано с тем, что JavaScript все еще новичок. В любом случае, ниже приведен код, который я написал:

    var requestURL = 'https://api.kraken.com/0/public/OHLC?pair=ETHEUR'

    var request = new XMLHttpRequest();
    request.open('GET',requestURL,true);
    request.responseType = 'json';

    request.onload = function(){ 
        var data = request.response; 
        console.log(data); 
    }


    request.setRequestHeader('Access-Control-Allow-Origin','*');

    request.send(); 

person Martin    schedule 11.08.2017    source источник
comment
Какова цель request.setRequestHeader('Access-Control-Allow-Origin','*')?   -  person guest271314    schedule 11.08.2017
comment
Ошибка говорит мне предоставить Access-Control-Allow-Origin, поэтому я добавил эту строку кода. Ясно, однако, что это не решило проблему.   -  person Martin    schedule 11.08.2017
comment
Ошибка уведомляет вас о том, что запрошенный ресурс не имеет заголовка Access-Control-Allow-Origin На запрошенном ресурсе отсутствует заголовок 'Access-Control-Allow-Origin'. Вы пытаетесь создать XMLHttpRequest() из file: протокола?   -  person guest271314    schedule 11.08.2017
comment
Да, как бы я это сделал? (Я предполагаю, что с file: protocol вы имеете в виду, что домен, из которого отправляется запрос, является путем к файлу, в котором я написал приведенный выше код.)   -  person Martin    schedule 11.08.2017
comment
В браузерах Chrome и Chromium вы можете запустить новый экземпляр браузера с установленным флагом --allow-file-access-from-files см. Чтение локального XML с помощью JS   -  person guest271314    schedule 11.08.2017
comment
Заголовки CORS управляются сервером ресурсов, клиент ничего не может с этим поделать   -  person Dayan Moreno Leon    schedule 11.08.2017


Ответы (1)


В случаях, подобных этому, когда сервер, на который вы пытаетесь сделать запрос из разных источников, не отправляет заголовок ответа Access-Control-Allow-Origin, ваш единственный вариант, если вы хотите сделать запрос на этот сервер из внешнего кода JavaScript, запущенного в браузере. , заключается в использовании прокси-сервера CORS. В противном случае ваш браузер не позволит вашему внешнему коду JavaScript получить доступ к ответу.

Итак, вы можете выполнить свой запрос, если измените свой код, чтобы он имел что-то вроде этого:

var proxyURL = 'https://cors-anywhere.herokuapp.com';
var requestURL = 'https://api.kraken.com/0/public/OHLC?pair=ETHEUR';
var request = new XMLHttpRequest();
request.open('GET', proxyURL + '/' + requestURL, true);

Это отправляет запрос через https://cors-anywhere.herokuapp.com, который перенаправляет запрос на https://api.kraken.com/0/public/OHLC?pair=ETHEUR, а затем получает ответ. Бэкэнд https://cors-anywhere.herokuapp.com добавляет к ответу заголовок Access-Control-Allow-Origin и передает его обратно в запрашивающий код внешнего интерфейса.

Затем браузер позволит вашему коду внешнего интерфейса получить доступ к ответу, потому что этот ответ с заголовком ответа Access-Control-Allow-Origin - это то, что браузер видит.

Вы также можете легко настроить собственный прокси-сервер CORS, используя https://github.com/Rob--W/cors-anywhere/

Также обратите внимание, что request.setRequestHeader('Access-Control-Allow-Origin','*') необходимо удалить из кода внешнего интерфейса, с помощью которого вы делаете запрос (как указано в комментариях выше).

Это потому, что Access-Control-Allow-Origin - это строго заголовок ответа, который серверы должны отправлять в ответах; отправка его со стороны клиента в запросе не будет иметь никакого эффекта, кроме как заставить ваш браузер выполнить ненужное запрос CORS preflight OPTIONS, который завершится ошибкой.

Для получения подробной информации о том, что браузеры делают, когда вы отправляете запросы из разных источников из внешнего кода JavaScript с помощью XHR или методов Fetch API или AJAX из библиотек JavaScript, а также подробности о том, какие заголовки ответов должны быть получены, чтобы браузеры разрешили внешнему коду доступ к ответы - см. https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS.

var proxyURL = 'https://cors-anywhere.herokuapp.com';
var requestURL = 'https://api.kraken.com/0/public/OHLC?pair=ETHEUR';

var request = new XMLHttpRequest();
request.open('GET', proxyURL + '/' + requestURL, true);
request.responseType = 'json';

request.onload = function() {
  var data = request.response;
  document.querySelector('pre').textContent = JSON.stringify(data, null, 2);
}

request.send();
<pre></pre>

person sideshowbarker    schedule 11.08.2017
comment
Спасибо за подробное объяснение и ссылку на то, где я могу узнать больше о том, как работают запросы на перекрестное происхождение. Тем не менее, я попытался реализовать свой запрос с помощью прокси-сервера CORS, как вы предложили. Однако при этом я не могу получить данные JSON, которые находятся на requestURL, вместо этого запрос извлекает содержимое на proxyURL. - person Martin; 11.08.2017
comment
Повторите попытку с request.open('GET', 'https://cors-anywhere.herokuapp.com/https://api.kraken.com/0/public/OHLC?pair=ETHEUR', true), и вы получите именно то, что вам нужно. См. Фрагмент кода, который я добавил к ответу. (В коде в первоначальном ответе я оставил конечный / в значении proxyURL, из-за которого запрос не работал должным образом.) - person sideshowbarker; 11.08.2017
comment
что, если https://cors-anywhere.herokuapp.com выйдет из строя или будет недоступен. откуда у тебя эти прокси? - person shorif2000; 10.01.2018
comment
@ Shortif2000 См. stackoverflow.com / questions / 47076743 /. Если у вас есть учетная запись Heroku, вы можете развернуть собственный CORS-прокси буквально за 2-3 минуты. - person sideshowbarker; 10.01.2018