javascript 维基百科 API + 跨域请求

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23952045/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 01:53:07  来源:igfitidea点击:

Wikipedia API + Cross-origin requests

javascriptcorswikipedia-api

提问by Pierre

I'm trying to access wikipedia using javascript+CORS

我正在尝试使用 javascript+ CORS访问维基百科

As far as I know, wikipedia should support CORS: http://www.mediawiki.org/wiki/API:Cross-site_requests

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

I tried the following script: create a XMLHttpRequest+credential/XDomainRequest, add some Http-Headers ( "Access-Control-Allow-Credentials",...) and send the query.

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

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

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();
        }
    };

But my script fails ('xhr.onerror' is called). How can I fix it ?

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

Thanks.

谢谢。

采纳答案by Daniel W.

CORS headers are sent to ALLOW a requesting script to access the contents.

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

Wikipedia is sending the CORS, not YOU.

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

Update according to the comments:

根据评论更新:

Wikipedia as an exception to general rule, by requiring you to append an originparameter to the URL you are requesting.

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

I think the reason behind this is related to caching. I don't know what kind of mechanism they are using, but it probably makes it easier and better for them to store a cache object and build variations that way.

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



More on CORS from MediaWiki API docs:

更多关于来自 MediaWiki API 文档的 CORS:

The MediaWiki API also requires that the origin be supplied as a request parameter, appropriately named "origin", which is matched against the Origin header requiredby the CORS protocol. Note that this header must be included in any pre-flight request, and so should be included in the query string portion of the request URI even for POST requests.

If the CORS origin check passes, MediaWiki will include the Access-Control-Allow-Credentials: true header in the response, so authentication cookies may be sent.

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

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

This means you have to send an Originheader to tell Wikipedia where you are coming from. Wikipedia is managing the access, not you.

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

Send this origin header:

发送这个源头:

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

Access-Control-Allow-*headers are responseheaders, not requestheaders.

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

Wikipedia additionally requires content type json:

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

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

回答by luckyguy73

I had the same problem while working on a freeCodeCamp project and the solution was so simple it made me laugh, since I had spent hours searching for it. In your jQuery URL include the parameter below.

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

&origin=*

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

回答by Adeel Siddiqui

As of today, Wikipedia supports CORS requests by using the normal ajax requests (no need of JSONP/callback manipulation). This can be done by setting the origin in the API call.

For authenticated requests, this must match the one of the one of the "origins" in the Origin header exactly (you need to set this using the beforeSend property while making an ajax call).
For unauthenticated requests, you can simply set it as an asterisk (*), and it works when using a simple $.getJSON from your domain. Example api call:
https://en.wikipedia.org//w/api.php?action=opensearch&format=json&origin=*&search=stack&limit=10
More at the MediaWiki API sandbox: MediaWiki API sandbox

截至今天,维基百科通过使用普通的 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 沙箱

回答by Aleksandr

You can use jQuery JSONP:

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

回答by kva

Adding origin=*alone with the url was not working for me so added withCredentials=false. It will work.

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

Those whoever facing issue again after adding `origin=*` . Try below one with `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();

credits to @muraliv

归功于@muraliv