Node.js 如何处理 POST 请求数据
原生 http 模块处理 POST 需监听 req 的 data/end 事件拼接请求体;Express 直接用 express.json() 和 express.urlencoded() 中间件解析,req.body 直接拿数据。注意校验数据与限制请求体大小。
两种方式:原生 http 模块要监听请求对象的 data/end 事件手动拼接请求体;Express 框架用内置的 express.json() / express.urlencoded() 中间件解析后,直接从 req.body 取数据。生产项目基本都用框架方式。
原生 http 方式
const http = require('http');
const server = http.createServer((req, res) => {
if (req.method === 'POST') {
const chunks = [];
let bytes = 0;
let rejected = false;
req.on('data', chunk => {
if (rejected) return;
bytes += chunk.length;
if (bytes > 1024 * 1024) {
rejected = true;
chunks.length = 0;
res.writeHead(413).end('Payload Too Large');
return;
}
chunks.push(chunk);
});
req.on('error', () => { rejected = true; chunks.length = 0; });
req.on('end', () => {
if (rejected) return;
const body = Buffer.concat(chunks).toString('utf8');
// 若约定JSON,需要验证Content-Type,并用try/catch处理JSON.parse错误。
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end('接收成功');
});
} else {
res.writeHead(404).end('Not Found');
}
});
server.requestTimeout = 30_000;
server.listen(3000);
小请求体可缓存到 end 再处理;大内容应流式处理。按 Buffer 合并后再解码,避免 UTF-8 字符跨 chunk 时损坏;还需按部署设置超时和并发限制。
Express 方式
const express = require('express');
const app = express();
app.use(express.json()); // 解析 application/json
app.use(express.urlencoded({ extended: true })); // 解析表单
app.post('/api/user', (req, res) => {
if (!req.body || typeof req.body.name !== 'string' || typeof req.body.email !== 'string') {
return res.status(400).json({ error: 'name 和 email 必须为字符串' });
}
const { name, email } = req.body;
res.json({ received: { name, email } });
});
app.listen(3000);
Express 4.16.0 起提供这两种内置解析中间件,常见 JSON/表单无需另装 body-parser;body-parser 仍是独立软件包。
生产注意事项
- 限制体积:
express.json({ limit: '1mb' }),防止超大请求体打爆内存; - 校验数据:用 zod/joi 等库校验 req.body 结构,永远不要信任客户端输入;
- 文件上传:express.json 处理不了 multipart,用 multer 或 busboy。
常见问题(FAQ)
Q:req.body 是 undefined?
最常见原因:没挂对应 Content-Type 的中间件,或客户端发送的 Content-Type 与中间件不匹配(比如发 JSON 但只挂了 urlencoded)。
Q:如何调试 POST 接口?
curl -X POST -H "Content-Type: application/json" -d '{"name":"Alice","email":"alice@example.com"}' http://localhost:3000/api/user,或用 Postman/Apifox。
Q:数据流式和一次性读取怎么选?
小体量 JSON/表单直接中间件一次性解析;大文件或大 payload 才需要流式边收边处理。