【问题标题】:Wikipedia API + Cross-origin requests维基百科 API + 跨域请求
【发布时间】:2014-07-20 01:30:37
【问题描述】:

我正在尝试使用 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')。我该如何解决?

【问题讨论】:

  • 失败怎么办?你得到什么信息?控制台出错?
  • AJAX.onerror 函数称为“糟糕,发出请求时出错。”
  • 维基百科必须发送 CORS 标头,而不是您。
  • @DanFromGermany 如果我删除对“setRequestHeader”的调用,它仍然会失败。
  • 你应该已经添加了真正的错误,使用控制台日志。 Refused to set unsafe header "Origin" (index):1 XMLHttpRequest cannot load http://en.wikipedia.org/w/api.php?action=opensearch&search=Javascript&format=json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://fiddle.jshell.net' is therefore not allowed access.

标签: javascript cors wikipedia-api


【解决方案1】:

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

&origin=*

Working CodePen

$.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){ /* ... */ }
);

【讨论】:

  • 你好,谢谢!我正在从事同一个项目,并且在使用 Wiki API 的 CORS 方面处于困境中。出于某种原因,当我读到以下内容时:“MediaWiki API 还要求将来源作为请求参数提供”,我没有意识到我必须按照您指出的那样做。这似乎有点奇怪,因为它不是托管通常设置允许标头的请求文件的站点吗?如:Access-Control-Allow-Origin: | *
  • 另外,您能否发布一个指向您找到此解决方案的链接?
  • 谢谢!我正在拔头发。昨天我能够使用 API,今天我不断收到跨源问题。添加这个允许我的请求再次工作。
  • XMLHttpRequest 无法加载 en.wikipedia.org/w/api.php?action=opensearch&origin=*&format=json&search=xxx。对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此不允许访问 Origin 'localhost:2222'。
  • 谢谢,其实我也在做fcc挑战
【解决方案2】:

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

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

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

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

MediaWiki API 沙箱中有更多内容:MediaWiki API sandbox

【讨论】:

  • 该示例仅在您在浏览器中执行时才可以在没有来源的情况下有效,如果您使用 AJAX 则无效。
【解决方案3】:

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

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

根据 cmets:

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

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


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

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

如果 CORS 来源检查通过,MediaWiki 将包含 Access-Control-Allow-Credentials:响应中的真实标头,所以 可能会发送身份验证 cookie。

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

发送这个源头:

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

Access-Control-Allow-* headers 是 response headers,而不是 request headers。

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

xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");

【讨论】:

  • 感谢您的回答。我更新了我的脚本jsfiddle.net/lindenb/Vr7RS/2 并设置了两个标题:这仍然不起作用。
  • @Pierre 你让它工作了吗?我试过但没有:S
  • 不,它没有,但据我了解 Ronni Skansing 的评论,en.wikipedia.org 似乎不允许 CORS。
  • 上面的注释:“应该包含在请求URI的查询字符串部分”。所以不能设置header,必须在实际url中加上'&origin=*。
  • 刚刚花了几天时间弄乱了 Apache 的 CORS 配置,却没有意识到这一点。非常感谢!
【解决方案4】:

你可以使用 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) { ... }
}

【讨论】:

    【解决方案5】:

    单独添加 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 的请求属性。已编辑。
    • 谁是“muraliv”?它指的是什么?一个答案?评论?
    猜你喜欢
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 2018-05-27
    • 2019-01-22
    相关资源
    最近更新 更多