【问题标题】:CORS error, but data is fetched regardlessCORS 错误,但无论如何都会获取数据
【发布时间】:2018-03-26 00:36:32
【问题描述】:

我在 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,没有更改默认配置。

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

“无法加载url:请求的资源上不存在‘Access-Control-Allow-Origin’标头。”等等

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

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

【问题讨论】:

    标签: javascript cors aws-api-gateway fetch-api


    【解决方案1】:

    fetch(`${url}`) 调用返回一个使用Response object 解析的承诺,并且Response 对象提供了使用textJSON dataBlob 解析的methods

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

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

    无法加载 url:请求的资源上没有“Access-Control-Allow-Origin”标头。”等

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

    因此,为了使上述代码正常工作,您需要修复该服务器上的服务器配置,以便它发送必要的 Access-Control-Allow-Origin 响应标头。

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

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

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

    我的问题:为什么响应在“网络”选项卡中没有显示错误,而同时在控制台中显示错误?

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

    【讨论】:

    • "浏览器本身在获取响应时没有遇到错误。但是您的代码遇到错误,因为它试图访问不存在的响应 - 因为浏览器没有将响应暴露给您的代码。”这正是我一直在寻找的。实际上,我在发布后不久就修复了错误本身,但它是那些巨大的“Whyyy”修复之一。现在我明白了。谢谢
    • “因为它试图访问不存在的响应” 这让我很困惑,因为我同时收到了 CORS 错误和响应数据(GET 调用) .
    【解决方案2】:

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

    在我看来,它就像是您的后端。 CORS 未激活,否则会打开该标头,之后,您会在前端客户端中看到有关源不匹配的错误。

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

    如果我看到除了 React 之外您还使用了哪些语言和/或框架,我可能会提供更好的输入。

    这就是你在 Express JS 和 node 中为你的后端所做的:

    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 请求。您可以从那里观察标题。

    【讨论】:

    • 我在网络选项卡中看到的 200 是同一个请求,它也成功地包含了我请求的数据。那不可能是选项,可以吗?
    • 尝试按 F12 在浏览器中打开开发工具,然后单击顶部的网络选项卡。你应该看到一切。您可能会看到 204 被解释为 200。
    • “如果我看到除了 React 还使用了哪些语言和/或框架,我可能会提供更好的输入。”处理 CORS 等的是 AWS API 网关。然后委托给 Lambda 函数,但我认为这不是问题。
    • "尝试按 F12 在浏览器中打开开发工具,然后单击顶部的网络选项卡。您应该会看到所有内容。您可能会看到 204 被解释为 200。"世界卫生大会?我现在正在查看 Chrome 中的“网络”选项卡。我看到了请求标头、响应标头和响应 JSON——一切看起来都应该如此。我唯一知道我有错误的地方是如果我查看控制台,或者setState 从未被调用过
    猜你喜欢
    • 1970-01-01
    • 2022-10-26
    • 2010-12-04
    • 1970-01-01
    • 2019-07-31
    • 1970-01-01
    • 2018-12-04
    • 2020-12-31
    • 1970-01-01
    相关资源
    最近更新 更多