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

如何在原生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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 10:16:30