Pracuję nad tym moim osobistym projektem dla zabawy, w którym chcę przeczytać plik xml, który znajduje się pod adresem http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml i przeanalizować xml i używaj go do przeliczania wartości między walutami.
Do tej pory wymyśliłem poniższy kod, który jest dość prosty, aby odczytać XML, ale pojawia się następujący błąd.
XMLHttpRequest nie może załadować ****. Żądany zasób nie zawiera nagłówka „Access-Control-Allow-Origin”. Dlatego Origin „ http://run.jsbin.com ” nie ma dostępu.
$(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ś może wskazać, co robię źle z moim kodem i jak mogę to naprawić.
javascript
jquery
ajax
xml-parsing
cors
Bazinga777
źródło
źródło
Odpowiedzi:
Nie będziesz w stanie wykonać wywołania Ajax do
http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml
z pliku wdrożonego w zhttp://run.jsbin.com
powodu zasad tego samego pochodzenia .Ponieważ strona źródłowa (inaczej strona pochodzenia ) i docelowy adres URL znajdują się w różnych domenach (
run.jsbin.com
iwww.ecb.europa.eu
), Twój kod w rzeczywistości próbuje wykonać żądanie międzydomenowe (CORS) , a nie zwykłeGET
.W kilku słowach zasada tego samego pochodzenia mówi, że przeglądarki powinny zezwalać na wywołania Ajax tylko do usług w tej samej domenie strony HTML.
Przykład:
Strona pod adresem
http://www.example.com/myPage.html
może bezpośrednio żądać tylko usług znajdujących się pod adresemhttp://www.example.com
, na przykładhttp://www.example.com/api/myService
. Jeśli usługa jest hostowana w innej domenie (powiedzmyhttp://www.ok.com/api/myService
), przeglądarka nie wykona połączenia bezpośrednio (jak można się spodziewać). Zamiast tego spróbuje wysłać żądanie CORS.Krótko mówiąc, aby wykonać żądanie (CORS) * w różnych domenach, Twoja przeglądarka:
Origin
nagłówek w pierwotnym żądaniu (z domeną strony jako wartość) i wykonuje to jak zwykle; i wtedyAccess-Control-Allow-Origin
jest jednym z nich ) zezwalające na żądanie CORS, przeglądarka zakończy wywołanie (prawie ** dokładnie tak, jak gdyby strona HTML znajdowała się w tej samej domenie).* Powyższe przedstawia kroki w prostym żądaniu, takim jak zwykły
GET
bez fantazyjnych nagłówków. Jeśli żądanie nie jest proste (np.POST
Zapplication/json
typem zawartości jako), przeglądarka zatrzyma je przez chwilę, a przed jego wypełnieniem najpierw wyśleOPTIONS
żądanie do docelowego adresu URL. Podobnie jak powyżej, będzie kontynuowane tylko wtedy, gdy odpowiedź na toOPTIONS
żądanie zawiera nagłówki CORS. ToOPTIONS
wywołanie jest znane jako żądanie wstępne .** Mówię prawie, ponieważ istnieją inne różnice między zwykłymi wywołaniami a wywołaniami CORS. 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 zostaną uwzględnione w
Access-Control-Expose-Headers
nagłówku.Jak to naprawić?
Czy to była tylko literówka? Czasami kod JavaScript zawiera tylko literówkę w domenie docelowej. Czy sprawdziłeś? Jeśli strona jest na
www.example.com
, będzie wykonywać tylko regularne połączeniawww.example.com
! Inne adresy URL, takie jakapi.example.com
lub nawetexample.com
lubwww.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 włączenia CORS jest dodanie niezbędnych nagłówków (as
Access-Control-Allow-Origin
) do odpowiedzi serwera. (Każdy serwer / język ma na to sposób - sprawdź tutaj kilka rozwiązań ).Ostatnia deska ratunku: jeśli nie masz dostępu do usługi po stronie serwera, możesz ją również skopiować (za pomocą narzędzi, takich jak odwrotne proxy ) i dołączyć tam wszystkie niezbędne nagłówki.
źródło
Access-Control-Allow-Origin
w tym adresie URL nagłówki nie będą miały żadnego znaczenia - przeglądarka otworzy adres URL jak zwykle. Zasady tego samego pochodzenia (i wymaganie dotycząceAccess-Control-Allow-Origin
nagłówka) mają zastosowanie tylko do wywołań Ajax.Jest na to pewien hackowy sposób, jeśli masz włączoną obsługę PHP na swoim 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 wydaje się mieć nic przeciwko temu, że ten adres URL pochodzi z innego źródła. Tak jak powiedziałem, to zręczna odpowiedź i jestem pewien, że jest z nią coś nie tak, ale dla mnie działa.
Edycja: Jeśli chcesz buforować wynik w php, oto plik php, którego użyjesz:
<?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 bierze się stąd .
źródło
file_get_contents
wywołania tylko wtedy, gdy najnowszy plik XML jest wystarczająco datowany. Nie zapomnij też o swoim nagłówku Content-Type :-)