CORS 错误,但无论如何都会获取数据

CORS error, but data is fetched regardless

我在 S3 存储桶中托管了一个生成的 React 站点。我的组件之一在加载时尝试获取某些内容:

require('isomorphic-fetch')
...

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

我正在获取的 url 是一个 AWS API 网关。我通过下拉菜单启用了 CORS,没有更改默认配置。

在我的控制台中,对于远程站点和开发期间的本地站点,我看到:

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

但是,在 Chrome 网络选项卡中,我可以看到请求和响应,状态为 200 等。在控制台中,我的 console.logthis.setState 永远不会然而,被调用了。

了解到CORS是一个普遍的痛点,很多问题都涉及到CORS。我的问题:为什么响应在“网络”选项卡中没有显示错误,而同时在控制台中显示错误?

您看到的可能是 OPTIONS 而不是 GET 的状态 200。 CORS 有一个设置来处理遗留问题,因此它不会让您的客户感到困惑。上次我不得不在 React 应用程序中这样做。您的错误是您的 CORS 配置不正确(显然很抱歉)。如果 Chrome 没有正确获取 header,它不会让您的客户端访问后端。其他浏览器可能也是,可能 React 也是。如果只有一侧启用了 CORS,则它可能是某种 HTTP 协议。有人可以在那里纠正我。这是与从 HTTPS 向 HTTP 发送请求类似的安全考虑。 Chrome 阻止它。

在我看来这是您的后端。 CORS 未处于活动状态,否则它会启用 header,之后,您会在前端客户端中看到有关来源不匹配的错误。

根据我的经验,这是一个 2-3 步组合,确保 OPTIONS 不要向您的客户发送令人困惑的信号(寻找与 200 相关的设置)。这是您后端的配置设置。然后,确保后端配置为使用 CORS。您非常具体地需要输入后端预期流量来自的源主机名和端口。

如果我看到除了 React 之外您还在使用哪些语言 and/or 框架,我可能会提供更好的意见。

这就是您在后端的 Express JS 和节点中执行的操作:

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 
}))

我的最后一个 React 应用程序在失败时通过抛出成功而在没有 optionsSuccessStatus 的情况下引爆。

为了给您一点图像来使用,CORS 很简单但也很挑剔。这是一个简单的对齐问题。一旦您的后端配置为 a) 使用 CORS 和 b) 知道要接受来自谁的流量,就完成了。一旦您的前端配置为处理此流量,就完成了。这就像在圆孔中对齐方形钉,直到您对齐配置设置。

尝试使用 Postman 向后端发送一些 GET 请求。您可以从那里观察 headers。

fetch(`${url}`) 调用 returns 一个用 Response object, and that Response object provides methods that resolve with text, JSON data, or a Blob 解决的承诺。

所以要得到你想要的数据,你需要做这样的事情:

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

这意味着浏览器不允许您的前端代码访问来自服务器的响应,因为响应不包括 Access-Control-Allow-Origin header.

因此,为了使上述代码正常工作,您需要修复该服务器上的服务器配置,以便它发送必要的 Access-Control-Allow-Origin 响应 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.

在服务器未发送 Access-Control-Allow-Origin 响应 header 的情况下,这是预期的。在那种情况下,浏览器仍然会收到响应——这就是为什么你可以在 devtools 网络选项卡中看到它——但仅仅因为浏览器收到响应并不意味着它会将响应公开给你的前端 JavaScript 代码.

浏览器只会让您的代码访问包含 Access-Control-Allow-Origin 响应的响应 header;如果响应不包含 header,则浏览器会阻止您的代码访问它。

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

出于上述原因。浏览器本身在获取响应时不会出错。但是你的代码遇到了一个错误,因为它试图访问一个不存在的 res object;浏览器尚未创建 res object,因为浏览器未公开对您的代码的响应。