jQuery xml 错误“请求的资源上不存在‘Access-Control-Allow-Origin’标头。”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19821753/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jQuery xml error ' No 'Access-Control-Allow-Origin' header is present on the requested resource.'
提问by Bazinga777
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.xmland parse the xml and use it to convert values between the currencies.
我正在研究我的这个个人项目只是为了好玩,我想阅读位于http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml的 xml 文件 并解析 xml 和使用它来转换货币之间的值。
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.
到目前为止,我已经想出了下面的代码,为了读取 xml,这是非常基本的,但我收到以下错误。
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.
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');
}
});
}
);
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.
我没有发现我的代码有任何问题,所以我希望有人能指出我的代码做错了什么以及如何修复它。
回答by acdcjunior
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 at http://run.jsbin.com
due to the same-origin policy.
由于同源策略,您将无法http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml
从部署在的文件进行 ajax 调用。http://run.jsbin.com
As the source (aka origin) page and the targetURL are at different domains (run.jsbin.com
and www.ecb.europa.eu
), your code is actually attempting to make a Cross-domain (CORS)request, not an ordinary GET
.
由于源(又名origin)页面和目标URL 位于不同的域(run.jsbin.com
和www.ecb.europa.eu
),您的代码实际上是在尝试发出跨域 (CORS)请求,而不是普通的GET
.
In a few words, the same-origin policysays that browsers should only allow ajax calls to services at the same domainof the HTML page.
简而言之,同源策略规定浏览器应该只允许对 HTML 页面相同域中的服务进行 ajax 调用。
Example:
例子:
A page at http://www.example.com/myPage.html
can only directly request services that are at http://www.example.com
, like http://www.example.com/api/myService
. If the service is hosted at another domain (say http://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.
页面 athttp://www.example.com/myPage.html
只能直接请求位于 的服务http://www.example.com
,例如http://www.example.com/api/myService
。如果服务托管在另一个域(例如http://www.ok.com/api/myService
),浏览器将不会直接进行调用(如您所料)。相反,它会尝试发出 CORS 请求。
To put it shortly, to perform a (CORS) request* across different domains, your browser:
简而言之,要跨不同域执行 (CORS) 请求*,您的浏览器:
- Will include an
Origin
header in the original request (with the page's domain as value) and perform it as usual; and then - Only ifthe server responseto that request contains the adequate headers (
Access-Control-Allow-Origin
is oneof 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).- If the expected headers don't come, the browser simply gives up (like it did to you).
- 将
Origin
在原始请求中包含一个标头(以页面的域作为值)并照常执行;进而 - 仅当对该请求的服务器响应包含允许 CORS 请求的足够标头(
Access-Control-Allow-Origin
是其中之一)时,浏览才会完成调用(几乎**与 HTML 页面位于同一域时的方式完全相同)。- 如果预期的标题没有出现,浏览器就会放弃(就像它对你所做的那样)。
* The above depicts the steps in a simplerequest, such as a regular GET
with no fancy headers. If the request is not simple (like a POST
with application/json
as content type), the browser will hold it a moment, and, before fulfilling it, will first send an OPTIONS
request to the target URL. Like above, it only will continue if the response to this OPTIONS
request contains the CORS headers. This OPTIONS
call is known as preflightrequest.
** I'm saying almostbecause 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.
* 以上描述了一个简单请求中的步骤,例如一个GET
没有花哨标题的常规请求。如果请求不简单(比如POST
with application/json
as 内容类型),浏览器会暂停一段时间,在完成之前,会先向OPTIONS
目标 URL发送请求。像上面一样,只有当对此OPTIONS
请求的响应包含 CORS 标头时,它才会继续。此OPTIONS
调用称为预检请求。
** 我这么说几乎是因为常规调用和 CORS 调用之间还有其他区别。一个重要的问题是,即使响应中存在某些标头,如果它们未包含在Access-Control-Expose-Headers
标头中,浏览器也不会选择它们。
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 to www.example.com
! Other URLs, such as api.example.com
or even example.com
or www.example.com:8080
are considered differentdomains by the browser! Yes, if the port is different, then it is a different domain!
这只是一个错字吗?有时 JavaScript 代码在目标域中只是一个错字。你检查了吗?如果页面在www.example.com
它只会定期调用www.example.com
! 其他 URL,例如api.example.com
甚至example.com
或www.example.com:8080
被浏览器视为不同的域!是的,如果端口不同,那么就是不同的域!
Add the headers.The simplest way to enableCORS 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.)
添加标题。启用CORS的最简单方法是将必要的标头 (as Access-Control-Allow-Origin
) 添加到服务器的响应中。(每个服务器/语言都有办法做到这一点 -在此处查看一些解决方案。)
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.
最后的手段:如果您没有对服务的服务器端访问权限,您也可以对其进行镜像(通过反向代理等工具),并在其中包含所有必要的标头。
回答by jyapayne
There's a kind of hack-tastic way to do it if you have php enabled on your server. Change this line:
如果您在服务器上启用了 php,则有一种 hack-tastic 方法可以做到这一点。改变这一行:
url: 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml',
to this line:
到这一行:
url: '/path/to/phpscript.php',
and then in the php script (if you have permission to use the file_get_contents() function):
然后在 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 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.
Php 似乎不介意该 url 是否来自不同的来源。就像我说的那样,这是一个笨拙的答案,我确定它有问题,但它对我有用。
Edit: If you want to cache the result in php, here's the php file you would use:
编辑:如果你想在 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;
?>
Caching code take from here.
缓存代码取自这里。