维基百科 API + 跨域请求

IT技术 javascript cors wikipedia-api
2021-03-14 19:37:11

我正在尝试使用 JavaScript 和CORS访问维基百科

据我所知,维基百科应该支持 CORS:http : //www.mediawiki.org/wiki/API :Cross-site_requests

我尝试了以下脚本:创建一个 XMLHttpRequest+credential/XDomainRequest,添加一些 HTTP 标头(“Access-Control-Allow-Credentials”等)并发送查询。

http://jsfiddle.net/lindenb/Vr7RS/

var WikipediaCORS=
    {
        setMessage:function(msg)
        {
            var span=document.getElementById("id1");
            span.appendChild(document.createTextNode(msg));
        },
        // Create the XHR object.
        createCORSRequest:function(url)
        {
            var xhr = new XMLHttpRequest();

            if ("withCredentials" in xhr)
            {
                xhr.open("GET", url, true);
            }
            else if (typeof XDomainRequest != "undefined")
            {
                xhr = new XDomainRequest();
                xhr.open(method, url);
            }
            else
            {
                return null;
            }
            xhr.setRequestHeader("Access-Control-Allow-Credentials", "true");
            xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
            return xhr;
        },
        init:function()
        {
            var _this = this;
            var url = 'http://en.wikipedia.org/w/api.php?action=opensearch&search=Javascript&format=json';
            var xhr = this.createCORSRequest(url);
            if (!xhr)
            {
                this.setMessage('CORS not supported');
                return;
            }

            xhr.onload = function()
            {
                _this.setMessage(xhr.responseText);
            };
            xhr.onerror = function()
            {
                _this.setMessage('Woops, there was an error making the request.');
            };
            xhr.send();
        }
    };

但是我的脚本失败了(调用了'xhr.onerror')。我该如何解决?

5个回答

我在处理freeCodeCamp项目时遇到了同样的问题,解决方案非常简单,让我发笑,因为我花了几个小时寻找它。在您的 jQuery URL 中包含以下参数。

&origin=*

工作代码笔

$.getJSON(
  'https://en.wikipedia.org/w/api.php?action=query&format=json&gsrlimit=15&generator=search' +
  '&origin=*' + // <-- this is the magic ingredient!
  '&gsrsearch='q, function(data){ /* ... */ }
);
另外,您能否发布一个指向您找到此解决方案的位置的链接?
2021-04-21 19:37:11
XMLHttpRequest 无法加载en.wikipedia.org/w/api.php?action=opensearch&origin= *&format=json&search=xxx。对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问源 ' localhost:2222 '。
2021-04-25 19:37:11
谢谢,事实上我也在做 fcc 挑战
2021-05-02 19:37:11
谢谢!我正在拔头发。昨天我能够使用 API,今天我不断遇到跨源问题。添加这个允许我的请求再次工作。
2021-05-03 19:37:11
哟,谢谢!我正在处理同一个项目,并且在使用 Wiki API 的 CORS 方面处于困境。出于某种原因,当我读到这个:“MediaWiki API 还要求将源作为请求参数提供”时,我没有意识到我只需要按照您指出的那样做。这似乎有点奇怪,因为它不是托管通常设置允许标头的请求文件的站点吗?如:Access-Control-Allow-Origin: <origin> | *
2021-05-21 19:37:11

截至 2016 年 8 月,维基百科通过使用普通的 Ajax 请求(不需要 JSONP/回调操作)来支持 CORS 请求。这可以通过在 API 调用中设置原点来完成。

对于经过身份验证的请求,这必须与 Origin 标头中的“来源”之一完全匹配(您需要在进行 Ajax 调用时使用 beforeSend 属性进行设置)。

对于未经身份验证的请求,您可以简单地将其设置为星号 (*),并且在使用来自您的域的简单 $.getJSON 时它可以工作。

示例 API 调用:
https://en.wikipedia.org//w/api.php?action=opensearch&format=json&origin=*&search=stack&limit=10

更多信息在 MediaWiki API 沙箱:MediaWiki API 沙箱

如果您在浏览器中执行该示例,则该示例仅在没有来源的情况下有效,如果您使用 AJAX 执行则无效。
2021-05-21 19:37:11

发送 CORS 标头以允许请求脚本访问内容。

维基百科发送的是 CORS,而不是

根据评论:

维基百科是一般规则的一个例外,它要求origin您在请求的 URL 中附加一个参数。

我认为这背后的原因与缓存有关。我不知道他们正在使用什么样的机制,但它可能让他们更容易和更好地存储缓存对象并以这种方式构建变体。


MediaWiki API 文档中有关 CORS 的更多信息:

MediaWiki API 还要求源作为请求参数提供,适当命名为“origin”,与 CORS 协议所需Origin 标头匹配请注意,此标头必须包含在任何飞行前请求中,因此即使对于 POST 请求,也应包含在请求 URI 的查询字符串部分中。

如果 CORS 源检查通过,MediaWiki 将在响应中包含 Access-Control-Allow-Credentials: true 标头,因此可能会发送身份验证 cookie。

这意味着你必须发送一个Origin标题来告诉维基百科你来自哪里。维基百科正在管理访问,而不是你。

发送这个源头:

xhr.setRequestHeader("Origin", "http://www.yourpage.com");

Access-Control-Allow-*标头是响应标头,而不是请求标头。

维基百科还需要内容类型json

xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
@Pierre 你让它工作了吗?我试过了,但没有:S
2021-04-24 19:37:11
不,它没有,但据我了解 Ronni Skansing 的评论,en.wikipedia.org 似乎不允许 CORS。
2021-04-25 19:37:11
只是花了几天时间弄乱了 Apache 的 CORS 配置而没有意识到这一点。非常感谢你!
2021-05-12 19:37:11
谢谢您的回答。我更新了我的脚本jsfiddle.net/lindenb/Vr7RS/2并设置了两个标题:这仍然不起作用。
2021-05-16 19:37:11
请注意上面的内容:“应包含在请求 URI 的查询字符串部分中”。所以你不能设置标题,你必须将 '&origin=* 添加到实际的 url。
2021-05-21 19:37:11

您可以使用 jQuery JSONP:

$.ajax( {
    url: "https://en.wikipedia.org/w/api.php",
    jsonp: "callback", 
    dataType: 'jsonp', 
    data: { 
        action: "query", 
        list: "search", 
        srsearch: "javascript", 
        format: "json" 
    },
    xhrFields: { withCredentials: true },
    success: function(response) { ... }
}

origin=*单独添加URL 对我不起作用,所以添加了withCredentials=false. 它会起作用。

添加后再次面临问题的人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 (this.readyState == 4 && this.status == 200) {
        console.log(this.responseText)
    }
};
xhttp.open("GET", url, true);
xhttp.withCredentials = false;
xhttp.setRequestHeader("Content-type", "application/json; charset=utf-8");
xhttp.send();

归功于@muraliv

有效,但您一再忘记this请求属性。已编辑。
2021-05-05 19:37:11
“穆拉利夫”是谁?它指的是什么?答案?一条评论?
2021-05-10 19:37:11