
本文教你用最简方式(cors 中间件)解决树莓派 Node.js 服务与本地网页间的跨域请求失败问题,无需深入理解 CORS 原理,专注实操配置与常见坑点。
本文教你用最简方式(`cors` 中间件)解决树莓派 node.js 服务与本地网页间的跨域请求失败问题,无需深入理解 cors 原理,专注实操配置与常见坑点。
在本地局域网项目(如 PC 控制树莓派 GPIO)中,CORS 报错(如 CORS request did not succeed)并非安全风险,而是浏览器对跨源请求的默认拦截机制。你已正确识别了核心矛盾:这不是线上部署问题,而是本地开发环境下的配置缺失。关键在于——Express 默认不处理 CORS 头,手动设置 res.writeHead() 不仅位置错误(应在路由处理前),且无法覆盖预检(preflight)请求所需的所有响应头。
✅ 正确解法:使用 cors 中间件(一行生效)
-
安装依赖
在树莓派项目目录下执行:npm install cors
-
修改服务器代码(关键顺序!)
将 cors() 中间件置于所有路由和 express.json() 之前:require('dotenv').config(); const express = require('express'); const cors = require('cors'); // ✅ 引入 const app = express(); const port = process.env.API_PORT || 6464; // ✅ 必须放在所有路由和解析中间件之前 app.use(cors()); // 允许任意源、任意方法、任意头(适合本地调试) // ✅ 解析 JSON 请求体(必须在 cors 之后,但仍在路由前) app.use(express.json()); app.use(express.urlencoded({ extended: true })); // 如需处理表单数据 // ✅ 路由定义(现在可正常接收 POST 数据) app.post('/toggle', (req, res) => { const state = req.body.state; // ⚠️ 注意:是 req.body,不是 req.query! console.log('Received state:', state); // 示例响应 res.json({ success: true, received: state }); }); app.listen(port, () => { console.log(`API server listening on http://localhost:${port}`); });
⚠️ 关键注意事项
- 前端 fetch 已正确:你的 Content-Type: application/json 和 JSON.stringify() 没问题,但后端必须用 express.json() 解析(已添加)。
- req.body vs req.query:POST 请求的数据在 req.body(需 express.json()),req.query 仅用于 URL 参数(如 /toggle?state=on)。
-
Firefox 的特殊限制:你发现 Firefox 对 localhost/局域网跨域更严格——这是已知行为。cors() 中间件可解决,但若仍失败,可临时添加明确配置:
app.use(cors({ origin: ['http://localhost:3000', 'http://192.168.68.75:8080'], // 替换为你的前端地址 methods: ['GET', 'POST'], allowedHeaders: ['Content-Type'] })); - 避免手动写响应头:res.writeHead() 在路由内调用会覆盖 Express 的标准响应流程,且无法处理 OPTIONS 预检请求——这正是 CORS request did not succeed 错误的根源。
✅ 验证步骤
- 重启树莓派上的 Express 服务;
- 确保前端页面通过 http://(非 file://)协议打开(例如用 live-server 启动);
- 在浏览器开发者工具 Network 标签页确认请求状态码为 200,且响应头包含 Access-Control-Allow-Origin: *。
至此,你的 COMP → fetch() → PI → GPIO 流程即可稳定运行。记住:本地开发优先用 cors() 中间件,而非手动拼接响应头;顺序决定成败,位置错则全盘失效。











