【问题标题】:react client wont follow redirect CORS localhost反应客户端不会跟随重定向CORS localhost
【发布时间】:2021-07-06 12:52:21
【问题描述】:

前端:localhost:3000 (react app) App.js (client) on load call api '/'

function fetch_redirect() {
  fetch("http://localhost:8082")
}

function App() {
  return <div className="App">{fetch_redirect()}</div>;
}

export default App;

后端:localhost:8082 (nodejs express app) 发送重定向到客户端上的 /test 端点

const express = require('express')
const app = express()
const cors = require('cors');

const whitelist = ['http://localhost:3000']
const corsOptions = {
  origin: function (origin, callback) {
      console.log(origin, whitelist.indexOf(origin) !== -1);
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  }
}

app.use(cors(corsOptions))
app.get('/', function (req, res) {
          res.redirect('http://localhost:3000/test')
    })
     
    app.listen(8082)

主要问题出在客户端 (react) 调用 API 后,重定向被阻止...如何让客户端响应应用程序遵循此重定向到 'http:/ /localhost:3000/test' 我的后端已经有了 cors,并启用了 localhost:3000 的白名单,以允许我不阻止 API 调用...但是 redirect 现在已从 fetch 前端阻止强>!

错误详情: CORS 策略已阻止从源“http://localhost:3000”访问“http://localhost:3000/test”(从“http://localhost:8082/”重定向)获取:无“访问” -Control-Allow-Origin' 标头存在于请求的资源上。如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源。

【问题讨论】:

  • 你用什么来运行 react 应用程序?我复制了您的代码并使用vite 运行客户端,一切正常。您可能需要修改您的5 客户端开发服务器
  • 使用 npm start 命令创建-react-app
  • 为了完成这项工作,我认为您需要更改 localhost:8082 快速代码以允许所有来源 - 而不仅仅是 http://localhost:3000。原因是,当请求跨源重定向时,浏览器会将 Origin 请求标头设置为 null。所以当localhost:8082 express代码看到请求时,Origin的值是null,而不是http://localhost:3000

标签: javascript node.js reactjs cors


【解决方案1】:

为了方便开发并拥有更接近生产环境的开发环境(无需使用Access-Control-Allow-Origin 降低安全级别),您应该有一个唯一的前端和后端入口点,与一个独特的来源(http://localhost:3000 在您的情况下)。

要实现这一点,请删除所有 Access-Control-* 标头,创建一个 src/setupProxy.js 文件并像这样填充它:

const { createProxyMiddleware } = require("http-proxy-middleware");

module.exports = app => {
  app.use(
    "/api",
    createProxyMiddleware ({
      target: "http://localhost:8082",
      changeOrigin: true
    })
  );
};

然后用npm install --save-dev http-proxy-middleware安装所需的express中间件作为开发依赖

注意:此功能适用于 react-scripts@2.0.0 及更高版本。

最后,将前端的所有fetch 替换为以/api 开头的相对URL

  • fetch("http://localhost:8082") 变为 fetch('/api'))
  • fetch('http://localhost:8082/some-endpoint') 这样的东西会变成fetch('/api/some-endpoint')

有关此的更多信息,请参阅docs

【讨论】:

    【解决方案2】:

    尝试像这样重构你的代码:

    const express = require('express')
    const app = express()
    const cors = require('cors');
    
    
    const whitelist = ['http://localhost:3000', 'http://localhost:8082'];
    
    
    const corsOptionsDelegate = (req, callback) => {
      var corsOptions;
      if (whitelist.indexOf(req.header('Origin')) !== -1) {
        corsOptions = { origin: true };
      } else {
        corsOptions = { origin: false };
      }
      callback(null, corsOptions);
    };
    
    const corsWithOptions = cors(corsOptionsDelegate);
    
    app.route('/')
      .options(corsWithOptions, (req, res) => { res.sendStatus(200); })
      .get(cors(), (req, res)=>{
           res.redirect('http://localhost:3000/test')
    });
    
    
    app.listen(8082)
    
    

    【讨论】:

      【解决方案3】:

      尝试在app.get 中使用next 函数:

      app.get('/', function (req, res, next) {
        res.redirect('http://localhost:3000/test');
        next();
      })
      

      此外,对于您的 ReactJS 应用程序(我不确定您的实现、CSR 或 SSR),您应该添加两件事:

      • Webpack:传递 CORS 的代理
        • 企业社会责任:
          devServer: {
            ...
            headers: {
              "Access-Control-Allow-Origin": "*",
              "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
              "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
            }
          }
          
        • SSR:将上述标头添加到webpackDevMiddleware 选项中。
      • 路线:
        • CSR:用于在开发端运行项目,使用:
          devServer: {
             historyApiFallback:{
               index:'build/index.html'
             },
          },
          
          对于 prod 端,使用spa 运行标志,例如serve 使用serve -s ./distpm2 运行pm2 start ./dist --spa
        • SSR:无需添加额外配置。

      【讨论】:

        【解决方案4】:

        试试这样的:

        whitelistedOrigins = ['http://localhost:3000'];
        app.use(cors({
            origin: whitelistedOrigins,
            methods: ['GET', 'PATCH', 'PUT', 'POST', 'DELETE', 'OPTIONS'],
            allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
        }));
        

        您可以根据需要修改方法/allowedHeaders 键...

        编辑:您的后端是:3000,不是问题吗?客户端不能同时在3000。

        【讨论】:

        • 后端在8082,前端在3000
        猜你喜欢
        • 2018-01-04
        • 1970-01-01
        • 2020-07-02
        • 2010-12-03
        • 1970-01-01
        • 2022-08-23
        • 2014-05-25
        • 1970-01-01
        • 2019-01-12
        相关资源
        最近更新 更多