2

The exact error that I am struggling with is "Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.".

I am trying to fetch JSON data using JavaScript from https://api.kraken.com/0/public/OHLC?pair=ETHEUR. I created a XMLHttpRequest object to do this, and specified GET as the type of request. This is supposedly a simple request, however the error says that a preflight request was sent. What is the reason for this behavior? That being said, to fix this error I tried to set a request header in which I specified '*' as the value for the Access-Control-Allow-Origin, yet I still get an error. I have looked through responses to similar questions as mine, but haven't been able to figure out how to solve the problem I am dealing with. This is probably due to still being very new to JavaScript. Either way, below is the code that I have written:

    var requestURL = 'https://api.kraken.com/0/public/OHLC?pair=ETHEUR'

    var request = new XMLHttpRequest();
    request.open('GET',requestURL,true);
    request.responseType = 'json';

    request.onload = function(){ 
        var data = request.response; 
        console.log(data); 
    }


    request.setRequestHeader('Access-Control-Allow-Origin','*');

    request.send(); 
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Martin
  • 33
  • 1
  • 5
  • What is purpose of `request.setRequestHeader('Access-Control-Allow-Origin','*')`? – guest271314 Aug 11 '17 at 01:50
  • The error is telling me to supply an Access-Control-Allow-Origin, hence why I added that line of code. Clearly however it did not resolve the problem. – Martin Aug 11 '17 at 01:56
  • The error is notifying you that the requested resource does not have `Access-Control-Allow-Origin` header _"No 'Access-Control-Allow-Origin' header is present on the requested resource."_ Are you trying to make an `XMLHttpRequest()` from `file:` protocol? – guest271314 Aug 11 '17 at 02:02
  • Yes, how would I go about doing that? (I am assuming that with file: protocol you mean the domain from which the request is being send is the path of the file I have written the above code in.) – Martin Aug 11 '17 at 02:10
  • At Chrome, Chromium browsers you can launch a new instance of the browser with `--allow-file-access-from-files` flag set see [Read local XML with JS](https://stackoverflow.com/q/41279589/) – guest271314 Aug 11 '17 at 02:13
  • CORS headers are manage by the resource server, the client can't do anything about it – Dayan Moreno Leon Aug 11 '17 at 03:56

1 Answers1

4

In cases like this where the server you’re trying to make a cross-origin request to doesn’t send the Access-Control-Allow-Origin response header, your only option, if you want to make a request to that server from frontend JavaScript code running in a browser, is to use a CORS proxy. Otherwise, your browser won’t allow your frontend JavaScript code to access the response.

So, you can make your request succeed if you change your code to have something like this:

var proxyURL = 'https://cors-anywhere.herokuapp.com';
var requestURL = 'https://api.kraken.com/0/public/OHLC?pair=ETHEUR';
var request = new XMLHttpRequest();
request.open('GET', proxyURL + '/' + requestURL, true);

That sends the request through https://cors-anywhere.herokuapp.com, which forwards the request to https://api.kraken.com/0/public/OHLC?pair=ETHEUR and then receives the response. The https://cors-anywhere.herokuapp.com backend adds the Access-Control-Allow-Origin header to the response and passes that back to your requesting frontend code.

The browser will then allow your frontend code to access the response because that response with the Access-Control-Allow-Origin response header is what the browser sees.

You can also easily set up your own CORS proxy using https://github.com/Rob--W/cors-anywhere/

Note also that request.setRequestHeader('Access-Control-Allow-Origin','*') needs to be removed from the frontend code you are making the request with (as mentioned in comments above).

That’s because Access-Control-Allow-Origin is strictly a response header for servers to send in responses; sending it from the client side in a request will have no effect other than to trigger your browser to do an unnecessary CORS preflight OPTIONS request that will fail.

For details about what browsers do when you send cross-origin requests from frontend JavaScript code using XHR or the Fetch API or AJAX methods from JavaScript libraries—and details about what response headers must be received in order for browsers to allow frontend code to access the responses—see https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS.

var proxyURL = 'https://cors-anywhere.herokuapp.com';
var requestURL = 'https://api.kraken.com/0/public/OHLC?pair=ETHEUR';

var request = new XMLHttpRequest();
request.open('GET', proxyURL + '/' + requestURL, true);
request.responseType = 'json';

request.onload = function() {
  var data = request.response;
  document.querySelector('pre').textContent = JSON.stringify(data, null, 2);
}

request.send();
<pre></pre>
Manikandan C
  • 668
  • 1
  • 9
  • 22
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
  • Thank you for the detailed explanation, and a reference to where I can learn more about how cross origin requests work. That said, I tried implementing my request with a CORS proxy as you suggested. However doing so I am not able to retrieve the JSON data that resides on the requestURL, instead the request fetches the contents on the proxyURL. – Martin Aug 11 '17 at 12:34
  • Please try again with `request.open('GET', 'https://cors-anywhere.herokuapp.com/https://api.kraken.com/0/public/OHLC?pair=ETHEUR', true)`, which will return exactly what you need. See the code snippet I added to the answer. (In the code in the initial answer I had left a trailing `/` in the `proxyURL` value that would have caused the request to not work as expected.) – sideshowbarker Aug 11 '17 at 14:58
  • what if `https://cors-anywhere.herokuapp.com` goes down or is unavailable. where do you get these proxies from? – shorif2000 Jan 10 '18 at 10:48
  • @shorif2000 See https://stackoverflow.com/questions/47076743/cors-anywhere-herokuapp-com-not-working/47085173#47085173. If you have a Heroku account, you can spin up a CORS proxy of your own in literally just 2-3 minutes – sideshowbarker Jan 10 '18 at 10:57