'Access-Control-Allow-Origin' 从 React(同构应用程序)发出 API 调用时出现问题

'Access-Control-Allow-Origin' issue when API call made from React (Isomorphic app)

我 运行 使用 React 和 Express 的同构 JavaScript 应用程序出现问题。

我正在尝试在我的组件安装时使用 axios.get 发出 HTTP 请求

componentDidMount() {
  const url = 'http://ufc-data-api.ufc.com/api/v3/iphone/fighters/title_holders';
  axios.get(url).then( res => {
    //use res to update current state
  })
}

我从 API 获得状态 200 res,但我没有获得任何响应数据并且在我的控制台中出现错误

XMLHttpRequest cannot load http://ufc-data-api.ufc.com/api/v3/iphone/fighters/title_holders. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:3000' is therefore not allowed access.

但是,如果我在 server.js

中提出请求
const url = 'http://ufc-data-api.ufc.com/api/v3/iphone/fighters/title_holders';
axios.get(url).then(res => {
    //console.log(res);
});

它工作正常,我在服务器启动时得到响应数据。这是实际 API 的问题还是我做错了什么?如果这是一个 CORS 问题,我猜 server.js 中的请求也不会起作用?谢谢!

因为服务器没有CORS header,所以你不能得到响应。

这是我从 Chrome 浏览器捕获的 API 中的 header:

Age:28
Cache-Control:max-age=3600, public
Connection:keep-alive
Date:Fri, 06 Jan 2017 02:05:33 GMT
ETag:"18303ae5d3714f8f1fbcb2c8e6499190"
Server:Cowboy
Status:200 OK
Via:1.1 vegur, 1.1 e01a35c1b8f382e5c0a399f1741255fd.cloudfront.net (CloudFront)
X-Amz-Cf-Id:GH6w6y_P5ht7AqAD3SnlK39EJ0PpnignqSI3o5Fsbi9PKHEFNMA0yw==
X-Cache:Hit from cloudfront
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN
X-Request-Id:b971e55f-b43d-43ce-8d4f-aa9d39830629
X-Runtime:0.014042
X-Ua-Compatible:chrome=1
X-Xss-Protection:1; mode=block

没有 CORS header 响应 headers.

CORS 是 浏览器 的一项功能。服务器需要选择加入 CORS 以允许浏览器绕过同源策略。您的服务器不会有相同的限制,并且能够向任何带有 public API 的服务器发出请求。 https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

在您的服务器上创建一个启用了 CORS 的端点,它可以充当您的 Web 应用程序的代理。

我认为你的问题的答案是

To have Chrome send Access-Control-Allow-Origin in the header, just alias your localhost in your /etc/hosts file to some other domain, like:

127.0.0.1 localhost yourdomain.com

使用名为 Allow-Control-Allow-Origin: * 的 google Chrome 扩展。它会在您的应用程序中即时修改 CORS headers。

我不知道这是否有帮助,但我在远程调试 react-native 应用程序时遇到了同样的错误。我是 运行 192.168.x.x:8081 上的调试器。我阅读了一些关于此 Cross-Origin Resource Sharing (CORS) 的内容,以了解什么是 CORS。 (我是初学者)并将我的 URL 从 IP:8081 更改为 localhost:8081,我的问题就解决了。

我遇到了同样的问题。其他答案是正确的,但还有另一种解决方案。 您可以设置响应 header 以允许 cross-origin 访问。 根据 this post,您必须在任何 app.get 调用之前添加以下代码:

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
  });

这对我有用:)

我今天遇到了同样的错误,使用带有 Typescript 的 React 和使用 Java Spring 启动的后端,如果你有后端的手,你可以简单地添加一个配置CORS 文件。

对于下面的示例,我将允许的原点设置为 * 以允许所有但您可以更具体地设置 url,例如 http://localhost:3000

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class AppCorsConfiguration {
    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

我在使用 fetch 命令时遇到了同样的问题。快速浏览 here 的文档告诉我们:

If the server you are requesting from doesn't support CORS, you should get an error in the console indicating that the cross-origin request is blocked due to the CORS Access-Control-Allow-Origin header being missing.

您可以使用no-cors模式来请求不透明的资源。

fetch('https://bar.com/data.json', {
  mode: 'no-cors' // 'cors' by default
})
.then(function(response) {
  // Do something with response
});
        //install cors using terminal/command  
        $ npm install cors

        //If your using express in your node server just add
        var cors = require('cors');
        app.use(cors())


       //and re-run the server, your problem is rectified][1]][1]
       **If you won't be understood then see below image**

https://i.stack.imgur.com/Qeqmc.png

不使用外部代理或 Chrome 扩展程序进行修复

应该在服务器端启用 CORS!如果你不能在服务器上激活它(例如使用外部 API)创建一个中间件 React -> Middleware -> Orginal Server.

  1. 创建一个 Node.js 项目(中间件)并在 app.js.

    中使用以下代码
    const express = require("express");
    var cors = require('cors')
    const app = express();
    app.use(cors());
    const { createProxyMiddleware } = require('http-proxy-middleware');
    app.use('/api', createProxyMiddleware({ 
        target: 'http://localhost:8080/', //original url
        changeOrigin: true, 
        //secure: false,
        onProxyRes: function (proxyRes, req, res) {
           proxyRes.headers['Access-Control-Allow-Origin'] = '*';
        }
    }));
    app.listen(5000);
    

这会将请求 http://localhost:5000/api/xxx 传递给原始服务器(例如 http://localhost:8080/api/xxx),并将结果 returns 传递给客户端。

  1. 更改客户端(React)调用proxy获取数据无CORS错误(只需要更改url中的端口):

    axios.get('http://localhost:5000/api/xxx', //proxy uri
    {
       headers: {
          authorization: ' xxxxxxxxxx' ,
          'Content-Type': 'application/json'
       } 
    }).then(function (response) {
       console.log(response);
    });
    
  2. 运行 节点项目 node app.js 和 React 项目 npm start.

在调试模式下使用 vs code 时可以使用此代码。

"runtimeArgs": ["--disable-web-security","--user-data-dir=~/ChromeUserData/"]

launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "chrome",
      "request": "launch",
      "name": "Chrome disable-web-security",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}",
      "runtimeArgs": [
        "--disable-web-security",
        "--user-data-dir=~/ChromeUserData/"
      ]
    }
  ]
}

或直接运行

Chrome --disable-web-security --user-data-dir=~/ChromeUserData/

Create-React-App 有一个简单的方法来处理这个问题:在 package.json 文件中添加一个代理字段,如下所示

"proxy": "http://localhost:8081",

在我的例子中,即使在服务器端启用它之后,我仍然收到 CORS 错误。问题是 url。 localhost:4001/todos 我忘了在前面加上 'http'。

http://localhost:4001/todos //correct way

您不必在客户端处理它。只需要以下步骤:

第 1 步:

npm install cors

第 2 步:

//express-server.js  

...
const cors = require('cors');
app.use(cors());

完成!

当您尝试通过 React 应用程序调用端点时,这是一个常见问题,因为 React 应用程序在 localhost:3000 上 运行,而 apis 在不同的服务器上。

纠正这个错误安装'http-proxy-middleware'

npm i http-proxy-middleware 
or
yarn add http-proxy-middleware

安装后在 src[=30 中创建一个 setupProxy.js =]文件夹

并遵循以下代码

    const { createProxyMiddleware } = require('http-proxy-middleware');
    
    module.exports = function(app) {
    
        app.use(
        '/getDetails', //this is your api
        createProxyMiddleware({
          target:'http://10.0.0.20:9000/getDetails', //this is your whole endpoint link
          changeOrigin: true,
        })
      );


    app.use(
        '/getproducts', //this is your api
        createProxyMiddleware({
          target:'http://10.0.0.20:9000/getproducts', //this is your whole endpoint link
          changeOrigin: true,
        })
      );
      
    };

您可以在 app.use 中添加任意数量的 api。 然后通常调用 api

axios.get('http://10.0.0.20:9680/getDetails')

有关更多详细信息,请查看下方 link Porxying API requests in Development in React JS

将代理添加到 package.json 文件并将 url 的剩余部分保留在提取本身中。

例如

在package.json文件中, "proxy" : "https://www.google.com", //添加自己的网站link

在 App.js 文件中 const response = await fetch(./...(根据你自己的))