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://run.jsbin.com
部署的文件对http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml
进行ajax调用http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml
同源政策 。)
As the source (aka origin ) page and the target URL 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 policy says that browsers should only allow ajax calls to services at the same domain of 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
.(位于http://www.example.com/myPage.html
的页面只能直接请求位于http://www.example.com
服务,例如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).(如果该服务托管在另一个域(例如http://www.ok.com/api/myService
),则浏览器将不会直接拨打电话(如您所愿)。) Instead, it will try to make a CORS request.(相反,它将尝试发出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;(将在原始请求中包含Origin
标头(以页面的域为值),并照常执行;) and then(然后)
Only if the server response to that request contains the adequate headers ( Access-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).(仅当服务器对该请求的响应包含允许CORS请求的足够的标头( Access-Control-Allow-Origin
就是其中之一 )时 ,浏览器才会完成调用(几乎完全是HTML页被执行的方式)在同一个域)。)
If the expected headers don't come, the browser simply gives up (like it did to you).(如果期望的标头没有出现,浏览器只会放弃(就像您所做的那样)。)
* The above depicts the steps in a simple request, such as a regular GET
with no fancy headers.(*上面描述了简单请求中的步骤,例如没有花式标题的常规GET
。) 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.(如果请求不是简单的(例如,以application/json
作为内容类型的POST
),浏览器将保留该请求一会儿,然后在执行该请求之前,首先将OPTIONS
请求发送到目标URL。) Like above, it only will continue if the response to this OPTIONS
request contains the CORS headers.(像上面一样,仅当对此OPTIONS
请求的响应包含CORS标头时,它才会继续。) This OPTIONS
call is known as preflight request.(此OPTIONS
调用称为预检请求。)
** I'm saying almost because there are other differences between regular calls and CORS calls.(**我说这几乎是因为常规电话和CORS电话之间还有其他差异。) 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.(重要的一点是,即使响应中存在某些标头,如果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.(有时,JavaScript代码在目标域中只是一个错字。) Have you checked?(你检查了吗) If the page is at www.example.com
it will only make regular calls to www.example.com
!(如果页面位于www.example.com
,则只会定期调用www.example.com
!) Other URLs, such as api.example.com
or even example.com
or www.example.com:8080
are considered different domains by the browser!(浏览器将api.example.com
甚至example.com
或www.example.com:8080
等其他URL视为不同的域!) 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.(启用 CORS的最简单方法是在服务器的响应中添加必需的标头(如Access-Control-Allow-Origin
)。) (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.(不得已:如果您没有服务器端对该服务的访问权限,则也可以对其进行镜像(通过反向代理之类的工具),并在其中包括所有必要的标头。) 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…