CORS error, but data is fetched regardless

流过昼夜 提交于 2020-04-13 04:14:39

问题


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?


回答1:


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 response 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 runs into an error because it’s trying to access a response that’s not there — because the browser isn’t exposing the response to your code.




回答2:


You may be seeing the status 200 for the OPTIONS not the GET. There is a setting for CORS to handle legacy, so it won't confuse your client. I had to do that last time in a React app. Your error is that your CORS isn't configured properly (sorry, obviously). Chrome won't let your client tlak to the backend if it doesn't get the headers properly. Other browsers probably also, probably React also. It may be some kind of HTTP protocol if only one side has CORS enabled. Someone can correct me there. It's a similar security consideration as sending a request to HTTP from HTTPS. Chrome blocks it.

It looks to me like it's your backend. CORS isn't active or it would put that header on, and after that, you would see errors about origin mismatch in the frontend client.

In my experience, it's a 2-3 step combo, make sure OPTIONS don't send confusing signals to your client (look for settings to do with 200). This is a config setting in your backend. Then, make sure the backend is configured to use CORS. You very specifically need to enter the origin hostname and port that the backend is to expect traffic from.

I could probably give better input if I see what languages and/or frameworks you are using besides React.

This is what you would do in Express JS and node for your Backend:

const cors = require('cors')

// note http or https
app.use(cors({
    origin: 'http://example.com:1337',
    //origin: '*',
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
    optionsSuccessStatus: 200
    // some legacy browsers (IE11, various SmartTVs) choke on 204 
}))

My last React app was detonating without optionsSuccessStatus by throwing success when it was fail.

To give you a little bit of imagery to work with, CORS is simple but finicky. It's a simple matter of alignment. Once your backend is configured to a) use CORS and b) know who to accept traffic from, it's done. Once your frontend is configured to handle this traffic, it's done. It's like aligning a square peg in a round hole until you get the config settings aligned.

Try using Postman to send some GET requests to the Backend. You can observe the headers from there.



来源:https://stackoverflow.com/questions/46737291/cors-error-but-data-is-fetched-regardless

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