I am working on this personal project of mine just for fun where I want to read an xml file which is located at http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml and parse the xml and use it to convert values between the currencies.
So far I have come up with the code below which is pretty basic in order to read the xml but I get the following error.
XMLHttpRequest cannot load ****. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://run.jsbin.com' is therefore not allowed access.
$(document).ready(
function() {
$.ajax({
type: 'GET',
url: 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml',
dataType: 'xml',
success: function(xml){
alert('aaa');
}
});
}
);
I don't see anything wrong with my code so I am hoping someone could point out what I am doing wrong with my code and how I could fix it.
You won't be able to make an ajax call to
http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml
from a file deployed athttp://run.jsbin.com
due to the same-origin policy.As the source (aka origin) page and the target URL are at different domains (
run.jsbin.com
andwww.ecb.europa.eu
), your code is actually attempting to make a Cross-domain (CORS) request, not an ordinaryGET
.In a few words, the same-origin policy says that browsers should only allow ajax calls to services at the same domain of the HTML page.
Example:
A page at
http://www.example.com/myPage.html
can only directly request services that are athttp://www.example.com
, likehttp://www.example.com/api/myService
. If the service is hosted at another domain (sayhttp://www.ok.com/api/myService
), the browser won't make the call directly (as you'd expect). Instead, it will try to make a CORS request.To put it shortly, to perform a (CORS) request* across different domains, your browser:
Origin
header in the original request (with the page's domain as value) and perform it as usual; and thenAccess-Control-Allow-Origin
is one of them) allowing the CORS request, the browse will complete the call (almost** exactly the way it would if the HTML page was at the same domain).* The above depicts the steps in a simple request, such as a regular
GET
with no fancy headers. If the request is not simple (like aPOST
withapplication/json
as content type), the browser will hold it a moment, and, before fulfilling it, will first send anOPTIONS
request to the target URL. Like above, it only will continue if the response to thisOPTIONS
request contains the CORS headers. ThisOPTIONS
call is known as preflight request.** I'm saying almost because there are other differences between regular calls and CORS calls. An important one is that some headers, even if present in the response, will not be picked up by the browser if they aren't included in the
Access-Control-Expose-Headers
header.How to fix it?
Was it just a typo? Sometimes the JavaScript code has just a typo in the target domain. Have you checked? If the page is at
www.example.com
it will only make regular calls towww.example.com
! Other URLs, such asapi.example.com
or evenexample.com
orwww.example.com:8080
are considered different domains by the browser! Yes, if the port is different, then it is a different domain!Add the headers. The simplest way to enable CORS is by adding the necessary headers (as
Access-Control-Allow-Origin
) to the server's responses. (Each server/language has a way to do that - check some solutions here.)Last resort: If you don't have server-side access to the service, you can also mirror it (through tools such as reverse proxies), and include all the necessary headers there.
There's a kind of hack-tastic way to do it if you have php enabled on your server. Change this line:
to this line:
and then in the php script (if you have permission to use the file_get_contents() function):
Php doesn't seem to mind if that url is from a different origin. Like I said, this is a hacky answer, and I'm sure there's something wrong with it, but it works for me.
Edit: If you want to cache the result in php, here's the php file you would use:
Caching code take from here.