如何在原生Node.js中获取HTTP请求体?
原生Node.js获取POST请求体的最优实现
你的代码能实现基础功能,但存在明显局限:它仅取第一个数据块body[0],如果请求体较大被拆分为多个chunk传输,就会丢失后续数据;同时缺少错误处理逻辑,一旦传输或解析出错会导致服务异常。下面是更可靠、更通用的优化实现:
1. 基础可靠的JSON请求体处理
const http = require('http'); const server = http.createServer((req, res) => { if (req.method === 'POST') { let bodyChunks = []; // 接收分块数据 req.on('data', (chunk) => { bodyChunks.push(chunk); }) // 处理传输错误 .on('error', (err) => { console.error('请求体读取失败:', err); res.statusCode = 400; res.end('Bad Request'); }) // 数据接收完成后解析 .on('end', () => { try { // 拼接所有chunk为完整Buffer,再转字符串 const bodyStr = Buffer.concat(bodyChunks).toString(); const parsedBody = JSON.parse(bodyStr); console.log('解析后的请求体:', parsedBody); res.statusCode = 200; res.end(JSON.stringify({ received: parsedBody })); } catch (err) { // 处理JSON解析错误 console.error('JSON格式错误:', err); res.statusCode = 400; res.end('Invalid JSON Format'); } }); } else { res.statusCode = 405; res.end('Method Not Allowed'); } }); server.listen(3000, () => { console.log('服务器运行在 http://localhost:3000'); });
核心优化点:
- 使用
Buffer.concat(bodyChunks)确保完整拼接所有数据块,避免丢失内容 - 添加
error事件监听,处理传输过程中的异常 - 用
try/catch包裹JSON解析逻辑,处理格式错误并返回对应HTTP状态码
2. 支持多种Content-Type的通用实现
如果需要处理表单数据(application/x-www-form-urlencoded)等其他格式,可以扩展逻辑:
const http = require('http'); const querystring = require('querystring'); const server = http.createServer((req, res) => { if (req.method === 'POST') { let bodyChunks = []; req.on('data', (chunk) => bodyChunks.push(chunk)) .on('error', (err) => { console.error('请求体读取失败:', err); res.statusCode = 400; res.end('Bad Request'); }) .on('end', () => { try { const bodyStr = Buffer.concat(bodyChunks).toString(); const contentType = req.headers['content-type']; let parsedBody; // 根据Content-Type适配解析逻辑 if (contentType === 'application/json') { parsedBody = JSON.parse(bodyStr); } else if (contentType === 'application/x-www-form-urlencoded') { parsedBody = querystring.parse(bodyStr); } else { // 其他格式直接返回原始字符串 parsedBody = bodyStr; } console.log('解析后的请求体:', parsedBody); res.statusCode = 200; res.end(JSON.stringify({ received: parsedBody })); } catch (err) { console.error('解析失败:', err); res.statusCode = 400; res.end('Invalid Request Body'); } }); } else { res.statusCode = 405; res.end('Method Not Allowed'); } }); server.listen(3000, () => { console.log('服务器运行在 http://localhost:3000'); });
3. 用Promise封装的优雅异步处理
如果想在异步函数中使用,可以把读取请求体的逻辑封装为Promise:
const http = require('http'); const querystring = require('querystring'); function parseRequestBody(req) { return new Promise((resolve, reject) => { if (req.method !== 'POST') { reject(new Error('仅支持POST请求')); return; } let bodyChunks = []; req.on('data', (chunk) => bodyChunks.push(chunk)); req.on('error', (err) => reject(err)); req.on('end', () => { try { const bodyStr = Buffer.concat(bodyChunks).toString(); const contentType = req.headers['content-type']; let parsedBody; if (contentType === 'application/json') { parsedBody = JSON.parse(bodyStr); } else if (contentType === 'application/x-www-form-urlencoded') { parsedBody = querystring.parse(bodyStr); } else { parsedBody = bodyStr; } resolve(parsedBody); } catch (err) { reject(err); } }); }); } // 使用示例 const server = http.createServer(async (req, res) => { try { const body = await parseRequestBody(req); console.log('请求体:', body); res.statusCode = 200; res.end(JSON.stringify({ success: true, data: body })); } catch (err) { console.error('处理错误:', err); res.statusCode = err.message.includes('仅支持POST') ? 405 : 400; res.end(err.message); } }); server.listen(3000, () => { console.log('服务器运行在 http://localhost:3000'); });
内容的提问来源于stack exchange,提问作者Nathanael Blocher
相关产品推荐
相关产品推荐

