Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CORS error, but data is fetched regardless

I have a generated React site I am hosting in an S3 bucket. One of my components attempts to fetch something when loaded:

require('isomorphic-fetch')
...

componentDidMount() {
  fetch(`${url}`)
    .then(res => {
      console.log(res);
      this.setState({
        users: res
      })
    })
    .catch(e => {
      // do nothing
    })
}

The url I am fetching is an AWS API Gateway. I have enabled CORS there, via the dropdown, with no changes to the default configuration.

In my console, for both the remote site and locally during development, I see:

"Failed to load url: No 'Access-Control-Allow-Origin' header is present on the requested resource." etc

However, in the Chrome Network tab, I can see the request and the response, with status 200, etc. In the console, my console.log and this.setState are never called, however.

I understand that CORS is a common pain point, and that many questions have touched on CORS. My question: Why does the response show no error in the Network tab, while simultaneously erroring in the console?

like image 778
Mitch Lillie Avatar asked Oct 13 '17 20:10

Mitch Lillie


1 Answers

The fetch(`${url}`) call returns a promise that resolves with a Response object, and that Response object provides methods that resolve with text, JSON data, or a Blob.

So to get the data you want, you need to do something like this:

componentDidMount() {
  fetch(`${url}`)
    .then(res => res.text())
    .then(text => {
      console.log(text);
      this.setState({
        users: text
    })
    .catch(e => {
      // do nothing
    })
}

Failed to load url: No 'Access-Control-Allow-Origin' header is present on the requested resource." etc

That means the browser isn’t allowing your frontend code to access the response from the server, because the response doesn’t include the Access-Control-Allow-Origin header.

So in order for the above code to work, you’ll need to fix the server configuration on that server so that it sends the necessary Access-Control-Allow-Origin response header.

However, in the Chrome Network tab, I can see the request and the response, with status 200, etc. In the console, my console.log and this.setState are never called, however.

That’s expected in the case where the server doesn’t send the Access-Control-Allow-Origin response header. In that case, the browser still gets the response — and that’s why you can see it in the devtools Network tab — but just because the browser gets the response doesn’t mean it will expose the response to your frontend JavaScript code.

The browser will only let your code access the response if it includes the Access-Control-Allow-Origin response header; if the response doesn’t include that header, then the browser blocks your code from accessing it.

My question: Why does the response show no error in the Network tab, while simultaneously erroring in the console?

For the reason outlined above. The browser itself runs into no error in getting the response. But your code hits an error because it’s trying to access an res object that’s not there; the browser hasn’t created that res object, because the browser isn’t exposing the response to your code.

like image 127
sideshowbarker Avatar answered Sep 28 '22 01:09

sideshowbarker