JQuery xml ошибка "Нет" Access-Control-Allow-Origin 'заголовок присутствует на запрошенном ресурсе.'

Я работаю над этим личным проектом для меня просто для удовольствия, где я хочу прочитать xml файл, который находится в http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml и проанализируйте xml и используйте его для преобразования значений между валютами.

До сих пор я придумал приведенный ниже код, который довольно прост для чтения xml, но я получаю следующую ошибку.

XMLHttpRequest не может загрузить ****. Нет "Access-Control-Allow-Origin" заголовок присутствует на запрошенном ресурсе. происхождения 'http://run.jsbin.com', следовательно, не допускается.

$(document).ready( 
    function() {     
        $.ajax({          
            type:  'GET',
            url:   'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml',
            dataType: 'xml',              
            success: function(xml){
                alert('aaa');
            }
         });
    }
);

Я не вижу ничего плохого в моем коде, поэтому я надеюсь, что кто-то может указать, что я делаю неправильно с моим кодом и как я могу это исправить.

Ответ 1

Вы не сможете сделать ajax-вызов http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml из файла, развернутого в http://run.jsbin.com из-за политики одного и того же происхождения.


Поскольку страница источника (ака источник) и целевой URL находятся в разных доменах (run.jsbin.com и www.ecb.europa.eu), ваш код на самом деле пытается сделать a запрос междоменной (CORS), а не обычный GET.

В нескольких словах политика одного и того же происхождения говорит, что браузеры должны разрешать только ajax-вызовы сервисам в одном домене страницы HTML.


Пример:

Страница в http://www.example.com/myPage.html может запрашивать только услуги, которые находятся на http://www.example.com, например http://www.example.com/api/myService. Если служба размещена в другом домене (скажем http://www.ok.com/api/myService), браузер не будет делать вызов напрямую (как и следовало ожидать). Вместо этого он попытается сделать запрос CORS.

Короче говоря, для выполнения запроса (CORS) * в разных доменах ваш браузер:

  • Будет включать заголовок Origin в исходном запросе (с доменом страницы как значение) и выполнять его как обычно; и затем
  • Только если ответ сервера на этот запрос содержит соответствующие заголовки (Access-Control-Allow-Origin является одним из них), разрешающий запрос CORS, просмотр завершит вызов (почти ** точно так, как если бы HTML-страница была в том же домене).
    • Если ожидаемые заголовки не появятся, браузер просто откажется (как и с вами).


* Выше описаны шаги в простом запросе, такие как обычный GET без заголовков. Если запрос не прост (например, POST с application/json в качестве типа содержимого), браузер мгновенно проведет его, и перед его выполнением сначала отправит запрос OPTIONS на целевой URL. Как и выше, он будет продолжаться, только если ответ на этот запрос OPTIONS содержит заголовки CORS. Этот вызов OPTIONS известен как запрос preflight.
** Я говорю почти потому, что существуют другие различия между обычными вызовами и вызовами CORS. Важно то, что некоторые заголовки, даже если они присутствуют в ответе, будут не отобраны браузером, если они не включены в Access-Control-Expose-Headers.


Как это исправить?

Это просто опечатка? Иногда код JavaScript имеет только опечатку в целевом домене. Вы проверили? Если страница находится в www.example.com, она будет делать регулярные вызовы www.example.com! Другие URL-адреса, такие как api.example.com или даже example.com или www.example.com:8080, рассматриваются браузером разные. Да, если порт отличается, то это другой домен!

Добавить заголовки. Самый простой способ включить CORS - добавить необходимые заголовки (как Access-Control-Allow-Origin) к ответам сервера. (Каждый сервер/язык имеет способ сделать это - проверить некоторые решения здесь.)

Последнее средство: Если у вас нет доступа к службе на стороне сервера, вы можете также зеркалировать его (с помощью таких инструментов, как обратные прокси), и включать все необходимые заголовки.

Ответ 2

Там какой-то взломанный способ сделать это, если на вашем сервере есть php. Измените эту строку:

url:   'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml',

в эту строку:

url: '/path/to/phpscript.php',

а затем в php script (если у вас есть разрешение на использование функции file_get_contents()):

<?php

header('Content-type: application/xml');
echo file_get_contents("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");

?>

Php, похоже, не возражает, если этот URL-адрес имеет другое происхождение. Как я уже сказал, это хакерский ответ, и я уверен, что с ним что-то не так, но он работает для меня.

Изменить: Если вы хотите кэшировать результат в php, здесь файл php вы будете использовать:

<?php

$cacheName = 'somefile.xml.cache';
// generate the cache version if it doesn't exist or it too old!
$ageInSeconds = 3600; // one hour
if(!file_exists($cacheName) || filemtime($cacheName) > time() + $ageInSeconds) {
  $contents = file_get_contents('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml');
  file_put_contents($cacheName, $contents);
}

$xml = simplexml_load_file($cacheName);

header('Content-type: application/xml');
echo $xml;

?>

Код кэширования от здесь.