CORS error even after setting Access-Control-Allow-Origin or other Access-Control-Allow-* headers on client side

wrahim picture wrahim · May 28, 2017 · Viewed 21.8k times · Source

I have a Vue application generated with webpack-simple option. I am trying to make a GET request to https://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=en but I get the error:

XMLHttpRequest cannot load https://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=en. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8080' is therefore not allowed access.

I am using vue-resource and have added:

Vue.http.headers.common['Access-Control-Allow-Origin'] = '*'

That has no effect.

I also added this in the devServer option in the webpack.config.js:

devServer: {
  historyApiFallback: true,
  noInfo: true,
  headers: {
    "Access-Control-Allow-Origin": "*"
  }
}

That isn't solving the problem either; the error message remains the same.

How to go about solving this?

Answer

sideshowbarker picture sideshowbarker · May 29, 2017

Access-Control-Allow-Origin is a response header the server the request goes to must send.

And all other Access-Control-Allow-* headers are response headers for servers to send.

If you don’t control the server your request is sent to, and the problem with the response from that server is just the lack of the Access-Control-Allow-Origin header or other Access-Control-Allow-* headers you can still get things to work—by making the request through a CORS proxy.

You can easily run your own proxy using code from https://github.com/Rob--W/cors-anywhere/.
You can also easily deploy your own proxy to Heroku in just 2-3 minutes, with 5 commands:

git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master

After running those commands, you’ll end up with your own CORS Anywhere server running at, e.g., https://cryptic-headland-94862.herokuapp.com/.

Now, prefix your request URL with the URL for your proxy:

https://cryptic-headland-94862.herokuapp.com/https://example.com

Adding the proxy URL as a prefix causes the request to get made through your proxy, which then:

  1. Forwards the request to https://example.com.
  2. Receives the response from https://example.com.
  3. Adds the Access-Control-Allow-Origin header to the response.
  4. Passes that response, with that added header, back to the requesting frontend code.

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

This works even if the request is one that triggers browsers to do a CORS preflight OPTIONS request, because in that case, the proxy also sends back the Access-Control-Allow-Headers and Access-Control-Allow-Methods headers needed to make the preflight successful.

And if you have frontend code that’s adding the Access-Control-Allow-Origin header or other Access-Control-Allow-* headers to the request on the client side, remove that code — because the only effect you have by adding those request headers is, you’re triggering your browser to send a CORS preflight OPTIONS request rather than the actual GET or POST request in your code.