Access-Control-Allow-Origin 与维基百科 API 与 Javascript

Access-Control-Allow-Origin with Wikipedia API with Javascript

正在尝试从 Codepen 上的维基百科 API 接收回复。回复应该是 json 我正在尝试 console.log.

但是在控制台中我看到一个错误:

Cross-Origin 请求被阻止:同源策略不允许读取位于 https://en.wikipedia.org/w/api.php?action=opensearch&search=earth&format=json 的远程资源。 (原因:缺少 CORS header ‘Access-Control-Allow-Origin’)。

在过去的几天里,我阅读了很多关于 CORS 和 Allow-Origin 的文章,试图理解,但出于某种原因,即使我认为我理解了......我也无法实施 :)

然而,最有趣的是这个 - 即使控制台显示这样的错误消息,如果我在开发人员工具网络选项卡中查看实际响应,我也会看到 json 响应!

最好能解释一下那怎么可能?

Codepen link here

var xhrObject = new XMLHttpRequest();

xhrObject.onreadystatechange = function() {
  if (xhrObject.readyState === 4 && xhrObject.status === 200) {
      console.log(xhrObject.responseText); 
    }
};

xhrObject.open(
  "POST", "https://en.wikipedia.org/w/api.php?action=opensearch&search=earth&format=json", true
);
xhrObject.send();

提前致谢

However, the most interesting thing is this - even though console shows such an error message if I look at the actual response in developer tools Network tab, I see the json response in all its glory!

It would be great to have an explanation how is that possible?

同源策略的要点是防止 Mallary(恶意网站的作者)使用 Alice 的网络浏览器(其中包含 Alice 的 cookie 和 Alice 的 IP 地址以及各种其他信息,将其标识为 Alice 的 浏览器)从 Bob 的网站(可能是 Alice 的网上银行或公司内联网)读取秘密数据。

不允许 Mallary 的 JavaScript 访问数据,除非 Bob 告诉 Alice 的浏览器让 JS 读取它是安全的(使用 CORS)。

Alice 的浏览器被允许访问数据,因为 Bob 已经信任 Alice 可以使用这些数据。 Mallary 无法访问 Alice 浏览器中的开发人员工具。

origin=* 添加到您使用的维基百科 URL 的查询参数中,请求将起作用。

要使 JavaScript Fetch/XHR 对维基百科 API 的请求有效,您必须在 URL 查询参数中包含 origin=* — 根据 the CORS-related docs for the Wikipedia backend:

For anonymous requests, origin query string parameter can be set to * which will allow requests from anywhere.

所以问题中的URL应该是这样的:

"https://en.wikipedia.org/w/api.php?action=opensearch&origin=*&search=earth&format=json"

……甚至像这样:

"https://en.wikipedia.org/w/api.php?action=opensearch&origin=*&search=earth="

(也就是说,我认为你可以省略 format=json 因为 JSON 输出似乎是默认的。)

那些在添加 origin=* 后再次面临问题的人。试试下面的 withCredentials = false

var xhttp = new XMLHttpRequest();
var url = "https://en.wikipedia.org/w/api.php?action=opensearch&limit=5&origin=*&search=simple";
xhttp.onreadystatechange = function () {
    if (readyState == 4 && status == 200) {
        console.log(responseText)
    }
};
xhttp.open("GET", url, true);
xhttp.withCredentials = false;
xhttp.setRequestHeader("Content-type", "application/json; charset=utf-8");
xhttp.send();