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

启用CORS仍遇Access-Control-Allow-Origin错误,树莓派植物控水网站问题

树莓派Node.js植物控水网站Socket.io跨域CORS问题

问题背景

在树莓派上搭建了基于Node.js的植物控水网站,通过数据库实现数据交互:Node.js连接数据库展示表格,用户修改表格内容后同步到数据库。网站在树莓派本地localhost:3000可正常运行,但用同一局域网的电脑访问(通过树莓派IP192.168.0.101:3000)时,出现Socket.io相关的CORS跨域错误。

错误信息

Access to XMLHttpRequest at 'http://localhost:3000/socket.io/?EIO=4&transport=polling&t=OvqJ4FV' from origin 'http://192.168.0.101:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
manager.js:108

GET http://localhost:3000/socket.io/?EIO=4&transport=polling&t=OvqJ4FV net::ERR_FAILED

value @ polling.js:298
i @ polling.js:237
value @ polling.js:190
value @ polling.js:215
value @ polling.js:96
value @ polling.js:56
value @ transport.js:46
value @ socket.js:170
a @ socket.js:111
value @ manager.js:108
(anonymous) @ manager.js:328
Show 9 more frames
Show less

当前代码(main.cjs)

const express = require('express');
const axios = require('axios');

const http = require('http');
const socketIo = require('socket.io');
var mysql = require('mysql2');

var plantData = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: '',
  database: "plants",
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});

const app = express();

const cors = require("cors");
const port2 = 5110;

app.listen(port2);
console.log("" + 3000);

app.use("*", cors());

const server = http.createServer(app);
server.listen(3000);
var io = socketIo(server);

app.set("view engine", "ejs");
app.set("views", "src2");

app.use(express.static("src2"));

app.get("/", (req, res) => {
  res.render("ejs/main.ejs");
  res.setHeader("Allow-Access-Control-Header", "*");
});
var howManyPlants = 0;

app.get("/plants", (req, res) => {
  return new Promise((resolve, reject) => {
      plantData.query("SELECT * FROM `plants` order by id asc"
        , (err, results) => {
          if (err) {
            console.log(err);
          } else {
            resolve(results);
          }
          var plants = results;
          //res.setHeader("Allow-Access-Control-Header", "*");
          res.json(plants);
          
          howManyPlants = plants.length;
        });
    });
});

app.get("/maxPlantId", (req, res) => {
  new Promise((resolve, reject) => {
    plantData.query(`Select max(id) from plants`, (err, results) => {
      if (err) {
        console.log(err);
      } else {
        resolve(results);

        plantIdNow = res.json(results);
      }
    });
  });
});

io.on("connection", (socket) => {
  socket.on("setAllPlantsTime", (time) => {
    return new Promise((resolve, reject) => {
      console.log("1");
      plantData.query(`UPDATE plants set plantTime = "${time}"`, (err, results) => {
        if (err) {
          console.log(err);
        } else {
          resolve(results);
        }
      });
  });
  });

  socket.on("changePlantProperty", (property) => {
    var plantId = property.id;
    var plantProperty = property.property;
    var plantPropertyValue = property.value;

    console.log(plantId + " " + plantProperty + " " + plantPropertyValue);

    return new Promise((resolve, reject) => {
      plantData.query(`UPDATE plants set ${plantProperty} = "${plantPropertyValue}" where id = ${plantId}`, (err, results) => {
        console.log(`UPDATE plants set ${plantProperty} = "${plantPropertyValue}" where id = ${plantId}`);
        if (err) {
          console.log(err);
        } else {
          resolve(results);
        }
      });
    });
  });

  socket.on("deletePlant", (plantId) => {
    return new Promise((resolve, reject) => {
      plantData.query(`Delete from plants where id = ${plantId}`, (err, results) => {
        if (err) {
          console.log(err);
        } else {
          resolve(results);
        }
      });
    });
  });

  socket.on("createPlant", (plantInput) => {
    var plantId = plantInput.id;
    var plantTime = plantInput.plantTime;
    var plantWeekDays = plantInput.plantWeekDays;
    var plantWater = plantInput.plantWater;

    console.log(plantId + " " + plantTime + " " + plantWeekDays + " " + plantWater);

    return new Promise((resolve, reject) => {
      plantData.query(`INSERT INTO plants VALUES ('` + plantId +`','` + plantTime + `','` + plantWeekDays + `','` + plantWater + `')`, (err, results) => {
        if (err) {
          console.log(err);
        } else {
          resolve(results);
        }
      });
    });
  });

  socket.on('disconnect', () => {
    console.log('disconnected');
  });
});

module.exports = {
  io
}

已尝试操作

  • 参考多种CORS相关教程配置,问题未解决
  • 当前使用XAMPP环境

解决方法

问题核心是Socket.io未配置CORS规则——你仅给Express应用配置了CORS,但Socket.io有独立的CORS配置项,需单独设置:

  1. 修改Socket.io初始化代码,添加CORS配置:
// 替换原有的var io = socketIo(server);
var io = socketIo(server, {
  cors: {
    origin: "*", // 开发环境可临时用*,生产环境建议指定具体IP/域名,比如"http://192.168.0.101:3000"
    methods: ["GET", "POST"]
  }
});
  1. 额外优化点:
    • 代码中同时启动了port2=5110和3000两个端口,若不需要可删除app.listen(port2);,避免资源浪费
    • res.setHeader("Allow-Access-Control-Header", "*");是错误的头名称,正确应为Access-Control-Allow-Origin,且已通过cors中间件配置,可直接删除该行
    • 数据库操作的Promise写法可优化,比如用util.promisify转换mysql的query方法,简化嵌套逻辑

验证修改

重启Node.js服务后,用电脑访问树莓派IP的3000端口,Socket.io跨域请求即可正常执行,不会再出现CORS错误。


内容的提问来源于stack exchange,提问作者Antoni Nabzdyk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 07:20:15