3

EDIT: No JSONP! Yes i know CORS is handled by the server and Yes the server does support it. The issue is on my side.

I am trying to use MediaWiki API from the browser. I am sending a GET request through XMLHttpRequest but due to CORS issues it's just not working. I am getting the following message from my browser after it receives the response:

XMLHttpRequest cannot load https://en.wikipedia.org/w/api.php?format=json&action=query&list=search&srsearch=Oculus&utf8. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8000' is therefore not allowed access.

I understand why i am getting this issue but i do not know how can i solve it from the browser/JavaScript side.

Code:

xmlhttp.open("GET","https://en.wikipedia.org/w/api.php?format=json&action=query&list=search&srsearch=" + subreddit + "&utf8",true);
xmlhttp.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
xmlhttp.send();

Some of the things i've tried:

xmlhttp.setRequestHeader('Access-Control-Allow-Origin', 'http://localhost');
xmlhttp.setRequestHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
xmlhttp.setRequestHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
xmlhttp.setRequestHeader('Access-Control-Allow-Credentials', true)
xmlhttp.setRequestHeader("Content-Type", "application/json; charset=UTF-8");

and setting the parameter origin in the url or as setRequestHeader which returned a invalid/bad Origin, denied.

Sneb
  • 151
  • 3
  • 8
  • possible duplicate of ["No 'Access-Control-Allow-Origin' header is present on the requested resource"](http://stackoverflow.com/questions/20035101/no-access-control-allow-origin-header-is-present-on-the-requested-resource) – kasper chexonz Sep 30 '15 at 06:53
  • add a callback-parameter and request the results in JSONP-format – Dr.Molle Sep 30 '15 at 07:00
  • _i do not know how can i solve it from the browser/JavaScript side_ CORS is set and controlled by the server. – Jaromanda X Sep 30 '15 at 07:01
  • to maybe clarify what @Dr.Molle suggested - you get jsonp from wikipedia by adding a (undocumented!) `callback=` parameter, in addition to `format=json` - and then read up on how to "do" jsonp successfully (i.e. you do not use XMLHttpRequest for instance) – Jaromanda X Sep 30 '15 at 07:04
  • 1
    So i get downvoted for asking a question that's valid? The "duplicate" question gives solutions such as using JSONP which is not what i want. Other answers say to set headers or are plainly wrong. To re-iterate i don't want to use JSONP. The best answer links to a blog that makes use of XDomainRequest() instead of XMLHttpRequest(). Upon comparison it seems that XDomainRequest() is needed instead for CORS compatibility. – Sneb Sep 30 '15 at 07:07
  • `To re-iterate i don't want to use JSONP` - put that in the question, and then you may as well delete your question because you **can not** fix a "lack of CORS" issue client side – Jaromanda X Sep 30 '15 at 07:09
  • `XDomainRequest` is (old?) Internet Exploder specific - so, not much of a solution at all – Jaromanda X Sep 30 '15 at 07:10
  • 1
    Then none of the answers in that "duplicate" question are valid. – Sneb Sep 30 '15 at 07:11
  • Yes they are, as you don't (or, didn't until just now) state your hesitance in using JSONP in your question – Jaromanda X Sep 30 '15 at 07:12
  • 1
    JSONP doesn't fix the issue, it just bypasses the CORS issue. MediaWiki supports CORS so i dont know why i'm getting this browser issue. – Sneb Sep 30 '15 at 07:15
  • _MediaWiki supports CORS_ - what makes you say this? – Jaromanda X Sep 30 '15 at 07:15
  • nevermind - found it in the documentation, which you should read – Jaromanda X Sep 30 '15 at 07:17
  • i think this? https://www.mediawiki.org/wiki/Manual:CORS and https://github.com/monsur/enable-cors.org/issues/55 edit: yes and i did try to set an origin parameter but it said it was refused. – Sneb Sep 30 '15 at 07:18
  • what did you set it to? same as the Origin header I hope – Jaromanda X Sep 30 '15 at 07:27
  • 1
    http://127.0.0.1:8000 – Sneb Sep 30 '15 at 07:45

3 Answers3

2

You can use JSONP.

<script src='https://en.wikipedia.org/w/api.php?format=json&action=query&list=search&srsearch=Oculus&utf8&callback=callbackname'></script>
<script>
    function callbackname(data){
       //you can get response data here
    }
</script>

If you use jquery.

$.getJSON('https://en.wikipedia.org/w/api.php?format=json&action=query&list=search&srsearch=Oculus&utf8&callback=?', function(data){
    //you can get response data here
})
Ming
  • 29
  • 2
  • 1
    is there a none JSONP way of handling this CORS issue? From what i've read it seems like a hacky way of bypassing the issue without really addressing it. – Sneb Sep 30 '15 at 07:13
  • the only CORS issue is that they don't issue CORS headers and you want them to – Jaromanda X Sep 30 '15 at 07:14
  • JSONP is also not a solution, as the callback parameter is not documented in their API – Jaromanda X Sep 30 '15 at 07:15
  • [CROS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) by set http header Access-Control-Allow-Origin on server. Or add a Proxy api in your server to fetch data from anthor server. – Ming Sep 30 '15 at 07:17
  • 1
    i've done that it didn't work. i've tried setting up many http headers and none fixed the issue. edited code above as an example. – Sneb Sep 30 '15 at 07:21
  • `Access-Control-Allow-*` headers are expected in the response from the server which has CORS enabled. The server/host to which you're making this request should send those headers in the response, only then browser will accept and process the response received. Setting these `Access-Control-Allow-*` headers in your request will not make it a CORS request :) – Arkantos Sep 30 '15 at 07:24
  • 1
    figured since it didn't work when i tried it even before it was mentioned here. – Sneb Sep 30 '15 at 07:27
1

As mentioned here, the origin parameter that you're passing in the request, and Origin header that is sent by your browser in the AJAX call should match and also it must match one of the values in $wgCrossSiteAJAXdomains on the foreign wiki. As your Origin (http://127.0.0.1:8000 or localhost:8000 in your case) won't be available in $wgCrossSiteAJAXdomains, MediaWiki API will never send Access-Control-Allow-Origin header in the response and any CORS request will fail with the error that you're seeing in your browser's console.

Another important fact to consider is that

MediaWiki API is used on Wikimedia sites to do things like allow image uploads directly to Commons from Wikipedia sites on the mobile interface.

This API is not for public consumption from any host, it's just for a set of validated hosts.

If you want to try some CORS requests, you can use GitHub API from here. Here's a sample pen making a CORS request to GitHub API and the JSON response is logged to DevTools Console.

Arkantos
  • 6,530
  • 2
  • 16
  • 36
  • 1
    But isn't the issue with CORS a security one that my browser implements? Why is there a server-side whitelist of origins for which CORS is allowed? From what i understand about CORS, my browser sends a request to A but the response is sent from B so it doesn't accept the response to be read. Am i misunderstanding the issue? – Sneb Sep 30 '15 at 15:25
  • Nope. CORS is about cross-domain requests. A script from domain A cannot make an AJAX call to domain B because of Same Origin Policy. CORS relaxes this restriction so that domain A script can make a call to domain B but it's up to domain B to respond to that request. If B trusts A then it will send `Access-Contol-Allow-*` headers and browser can process the response. On the other hand, if B doesn't know A, it will not send CORS specific headers and the browser will throw an error – Arkantos Sep 30 '15 at 16:18
1

It is not currently possible to do what you want because there is a server-side whitelist of origins for which CORS is allowed, and your server is not on the whitelist.

Currently there is no option in MediaWiki for auth-less CORS, so the whitelist is applied to all CORS requests, whether they include auth or not.

See https://phabricator.wikimedia.org/T62835 and https://www.mediawiki.org/wiki/Manual:CORS

Brion
  • 1,031
  • 6
  • 4
  • But isn't the issue with CORS a security one that my browser implements? Why is there a server-side whitelist of origins for which CORS is allowed? From what i understand about CORS, my browser sends a request to A but the response is sent from B so it doesn't accept the response to be read. Am i misunderstanding the issue? – Sneb Sep 30 '15 at 15:24