jQuery XML error 'No' Access-Control-Allow-Origin ' nagłówek jest obecny na żądanym zasobie.'

Pracuję nad moim osobistym projektem dla Zabawy, gdzie chcę przeczytać plik xml, który znajduje się w http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml i przeanalizować xml i użyć go do konwersji wartości między walutami.

Do tej pory wymyśliłem poniższy kod, który jest dość podstawowy, aby przeczytać xml, ale dostaję następujący błąd.

XMLHttpRequest nie może załadować****. Brak "Kontroli Dostępu-Zezwalaj Na Pochodzenie" nagłówek jest obecny na żądanym zasobie. Pochodzenie " http://run.jsbin.com ' nie jest zatem dozwolony dostęp.

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

Nie widzę nic złego w moim kodzie, więc mam nadzieję, że ktoś wskaże, co robię źle z moim kodem i jak Mogę to naprawić.

Author: sideshowbarker, 2013-11-06

2 answers

Nie będzie można wykonać połączenia ajax do http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml z pliku wdrożonego w http://run.jsbin.com ze względu na politykę samego pochodzenia.


Ponieważ strona źródłowa (aka origin) i adres URL target znajdują się w różnych domenach (run.jsbin.com i www.ecb.europa.eu), twój kod próbuje zrobić Cross-domain (Kors) prośba, nie zwykła GET.

W kilku słowach, Polityka samego pochodzenia mówi, że przeglądarki powinny tylko Zezwalaj na wywołania ajax do usług w tej samej domenie strony HTML.


Przykład:

Strona w http://www.example.com/myPage.html może bezpośrednio żądać tylko usług, które są w http://www.example.com, Jak http://www.example.com/api/myService. Jeśli usługa jest hostowana w innej domenie (powiedzmy http://www.ok.com/api/myService), przeglądarka nie wykona połączenia bezpośrednio (jak można się spodziewać). Zamiast tego spróbuje złożyć wniosek CORS.

Krótko mówiąc, aby wykonać (CORS) żądanie * w różnych domenach, Twój przeglądarka:

  • zawiera nagłówek Origin w pierwotnym żądaniu (z domeną strony jako wartością) i wykonuje go jak zwykle; a następnie
  • tylko wtedy, gdy odpowiedź serwera na to żądanie zawiera odpowiednie nagłówki (Access-Control-Allow-Origin jest jeden z nich) zezwalając na żądanie CORS, przeglądanie zakończy połączenie (prawie * * dokładnie tak, jak gdyby strona HTML była w tej samej domenie).
    • jeśli oczekiwane nagłówki nie przychodź, przeglądarka po prostu się poddaje(tak jak Tobie).


* powyższe przedstawia kroki w prostym żądaniu , takim jak zwykłe GET bez wymyślnych nagłówków. Jeśli żądanie nie jest proste (np. POST z application/json jako typem zawartości), przeglądarka zatrzyma je na chwilę, a przed jego wypełnieniem wyśle zapytanie OPTIONS na adres docelowy. Tak jak wyżej, będzie ona kontynuowana tylko wtedy, gdy odpowiedź na to OPTIONS żądanie zawiera Kors nagłówki. To OPTIONS wywołanie jest znane jako Preflight request.
** mówię o prawie ponieważ istnieją inne różnice między regularnymi połączeniami a połączeniami KORSOWYMI. Ważne jest to, że niektóre nagłówki, nawet jeśli są obecne w odpowiedzi, nie zostaną odebrane przez przeglądarkę, jeśli nie są zawarte w Access-Control-Expose-Headers nagłówek.


Jak to naprawić?

To była tylko literówka? czasami JavaScript kod ma tylko literówkę w domenie docelowej. Sprawdziłeś? Jeśli strona znajduje się w www.example.com, będzie wykonywać tylko regularne połączenia do www.example.com! Inne adresy URL, takie jak api.example.com lub nawet example.com lub www.example.com:8080 są uważane za różne domeny przez przeglądarkę! Tak, jeśli port jest inny, to jest to inna domena!

Dodaj nagłówki.najprostszym sposobem na włączenie CORS jest dodanie niezbędnych nagłówków (jako Access-Control-Allow-Origin) do odpowiedzi serwera. (Każdy serwer / język ma sposób na zrób to- sprawdź kilka rozwiązań tutaj.)

Ostatnia deska ratunku: jeśli nie masz dostępu do usługi po stronie serwera, możesz ją również mirrorować (za pomocą narzędzi takich jak reverse proxy) i dołączyć tam wszystkie niezbędne nagłówki.

 163
Author: acdcjunior,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:31

Jest na to swego rodzaju hack-Tasty sposób, jeśli masz włączone php na serwerze. Zmień tę linię:

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

Do tej linii:

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

A następnie w skrypcie php (jeśli masz uprawnienia do używania funkcji file_get_contents ()):

<?php

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

?>

Php nie ma nic przeciwko, jeśli ten adres url jest z innego pochodzenia. Jak mówiłem, to jest hacky odpowiedź, i jestem pewien, że coś jest nie tak z tym, ale to działa dla mnie.

Edytuj: Jeśli chcesz buforować wynik w php, oto plik php, którego byś użył:

<?php

$cacheName = 'somefile.xml.cache';
// generate the cache version if it doesn't exist or it's 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;

?>

Kod buforowania weź z tutaj .

 29
Author: jyapayne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:26