Wikipedia API + Cross-origin requests

妖精的绣舞 提交于 2019-12-17 09:30:43

问题


I'm trying to access wikipedia using javascript+CORS

As far as I know, wikipedia should support 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.

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 ?

Thanks.


回答1:


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

Wikipedia is sending the CORS, not YOU.

Update according to the comments:

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

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:

The MediaWiki API also requires that the origin be supplied as a request parameter, appropriately named "origin", which is matched against the Origin header required by 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.

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

Send this origin header:

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

Access-Control-Allow-* headers are response headers, not request headers.

Wikipedia additionally requires content type json:

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



回答2:


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.

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



回答3:


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




回答4:


You can use 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:


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

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



来源:https://stackoverflow.com/questions/23952045/wikipedia-api-cross-origin-requests

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!