You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Node.js部署CPanel遇CORS跨域拦截问题求助

CPanel部署React+Node.js后CORS问题排查

目录结构

public_html
|- 2nd react app
   |- .htaccess
   |- all the builded react file
|- backend (node js)
   |- .htaccess
   |- index.js
   |- all the node js file
|- all the builded react file
|- .htaccess 

问题现象

Access to XMLHttpRequest at 'https://api.myweb.com/auth/login' from origin 'https://myweb.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

本地用Postman测试后端正常,部署到CPanel后出现上述跨域错误,且第二个React应用负责发起所有请求。

已尝试的配置

1. Node.js后端CORS配置

require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const { sequelize } = require('./utils/db');
const authMiddleware = require('./middlewares/auth');
const cookieParser = require("cookie-parser");
const app = express();
const corsOptions = {
  origin: 'https://myweb.com',
  optionsSuccessStatus: 200,
  credentials: true
}

app.use(cors(corsOptions));
app.use(bodyParser.json());
app.use(cookieParser(process.env.JWT_KEY));

app.use('/auth', require('./routes/auth'));
app.use('/products',authMiddleware, require('./routes/product'));

sequelize.sync()
    .then(() => {
        app.listen(3000, () => {
            console.log('Server started on port 3000');
        });
    })
    .catch(err => {
        console.log(err);
    });

2. 后端目录.htaccess配置

# DO NOT REMOVE. CLOUDLINUX PASSENGER CONFIGURATION BEGIN
PassengerAppRoot "/home/project/public_html/api.myweb.com"
PassengerBaseURI "/"
PassengerNodejs "/home/project/nodevenv/public_html/api.myweb.com/18/bin/node"
PassengerAppType node
PassengerStartupFile index.js
# DO NOT REMOVE. CLOUDLINUX PASSENGER CONFIGURATION END
# DO NOT REMOVE OR MODIFY. CLOUDLINUX ENV VARS CONFIGURATION BEGIN
# DO NOT REMOVE OR MODIFY. CLOUDLINUX ENV VARS CONFIGURATION END
<IfModule mod_headers.c>
    SetEnvIf Origin "^https?://([a-zA-Z0-9-]+\.)?(myweb\.com)$" CORS_ALLOW_ORIGIN=$0
    Header set Access-Control-Allow-Origin %{CORS_ALLOW_ORIGIN}e env=CORS_ALLOW_ORIGIN
</IfModule>

3. 根目录.htaccess配置

<IfModule mod_rewrite.c>

  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /index.html [L]

</IfModule>

4. 第二个React应用目录.htaccess配置

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /otherapp/
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_FILENAME} !-l
  RewriteRule . /otherapp/index.html [L]
  </IfModule>

可能的修复方案

  • 验证Passenger路径正确性:后端.htaccess中的PassengerAppRoot指向"/home/project/public_html/api.myweb.com",但实际后端目录是public_html/backend,需确认路径是否匹配,路径错误会导致Node应用无法正常启动,进而无法返回CORS头。
  • 动态匹配CORS Origin:调整CORS配置为动态规则,兼容无origin的请求(如Postman):
    const corsOptions = {
      origin: function (origin, callback) {
        const allowedOrigins = ['https://myweb.com'];
        if (!origin || allowedOrigins.includes(origin)) {
          callback(null, true);
        } else {
          callback(new Error('Not allowed by CORS'));
        }
      },
      optionsSuccessStatus: 200,
      credentials: true
    };
    
  • 手动处理预检请求:在Express中显式处理OPTIONS请求,确保预检请求能得到正确响应:
    // 放在cors中间件之后
    app.options('*', cors(corsOptions));
    
  • 检查环境变量加载:确认CPanel上Node应用的.env文件是否存在且配置正确,dotenv是否能读取到环境变量,若JWT_KEY缺失,cookie-parser中间件异常可能影响后续中间件执行。
  • 启用mod_headers模块:在CPanel的Apache模块管理中确认mod_headers已启用,否则.htaccess中的Header配置不会生效。
  • 检查域名解析:确认api.myweb.com确实指向后端目录,无重定向或配置错误导致请求落到静态文件目录。

内容的提问来源于stack exchange,提问作者Rayhan Prastya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 05:55:42