jQuery xml错误'没有'Access-Control-Allow-Origin'标题出现在请求的资源上。

我正在从事这个个人项目,只是为了好玩,我想读一个位于http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml的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'); } }); } ); 

我没有看到我的代码有什么问题,所以我希望有人能指出我在做什么错了我的代码以及如何修复它。

您将无法通过http://run.jsbin.com部署的文件向http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml进行ajax调用,因为同源政策 。

由于源(aka origin )页面和目标 URL位于不同的域( run.jsbin.comwww.ecb.europa.eu ),因此您的代码实际上正尝试创建一个跨域(CORS)请求,而不是普通的GET

简而言之, 同源策略指出,浏览器应该只允许在HTML页面的同一个域上对服务进行Ajax调用。

例:

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 如果请求不是简单的(比如application/json作为内容类型的POST ),浏览器会暂停一会儿,在完成之前,会首先向目标URL发送OPTIONS请求。 像上面一样,只有当对这个OPTIONS请求的响应包含CORS头时,它才会继续。 这个OPTIONS调用被称为预检请求。
**我说的几乎是因为常规电话和CORS电话之间还有其他区别。 一个重要的问题是,如果浏览器中没有包含某些标题(即使存在于响应中),它们将不会被Access-Control-Expose-Headers如果它们不包含在Access-Control-Expose-Headers标题中。

如何解决它?

这只是一个错字吗? 有时JavaScript代码在目标域中只有一个错字。 你检查过了吗? 如果该网页位于www.example.com ,则只会定期拨打www.example.com ! 其他网址(如api.example.com或甚至example.comwww.example.com:8080被浏览器视为不同的网域! 是的,如果端口是不同的,那么这是一个不同的领域!

添加标题。 启用 CORS的最简单方法是将必要的标题(如Access-Control-Allow-Origin )添加到服务器的响应中。 (每个服务器/语言都有办法做到这一点 – 在这里查看一些解决方案 。)

最后的手段:如果您没有对服务的服务器端访问权限,您也可以对其进行镜像(通过反向代理等工具),并在其中包含所有必要的标头。

如果您的服务器上启用了PHP,那么有一种破解的方法可以做到这一点。 改变这一行:

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

到这一行:

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

然后在php脚本中(如果你有权限使用file_get_contents()函数):

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

Php似乎不介意,如果这个网址是从不同的起源。 就像我说的那样,这是一个拙劣的答案,我确定它有什么问题,但对我来说很有用。

编辑:如果你想在PHP中缓存结果,这里是你将使用的PHP文件:

 <?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; ?> 

缓存代码从这里获取 。