从Node.js的http.IncomingMessage获取请求体

35

我正在尝试为一个使用node.js编写的应用程序实现一个简单的HTTP端点。我已经创建了HTTP服务器,但现在我卡在读取请求内容主体上:

http.createServer(function(r, s) {
    console.log(r.method, r.url, r.headers);
    console.log(r.read());
    s.write("OK"); 
    s.end(); 
}).listen(42646);

请求的方法、URL和头部信息都已经正确输出,但是r.read()始终为空。我可以确定这不是请求发送的问题,因为服务器端的content-length头部信息大于零。

文档说明 r 是一个实现了可读流接口的http.IncomingMessage对象,那么为什么它没有起作用呢?

3个回答

43
'readable' 事件有问题,它错误地在正文字符串末尾添加了额外的空字符。
使用“data”事件处理流时处理数据块:
http.createServer((r, s) => {
    console.log(r.method, r.url, r.headers);
    let body = '';
    r.on('data', (chunk) => {
        body += chunk;
    });
    r.on('end', () => {
        console.log(body);
        s.write('OK'); 
        s.end(); 
    });
}).listen(42646); 

28

好的,我认为我找到了解决方案。在node.js中,r流(就像其他任何东西一样,傻瓜式的我...)应该以异步事件驱动的方式读取:

http.createServer(function(r, s) {
    console.log(r.method, r.url, r.headers);
    var body = "";
    r.on('readable', function() {
        body += r.read();
    });
    r.on('end', function() {
        console.log(body);
        s.write("OK"); 
        s.end(); 
    });
}).listen(42646);

9
这不仅是一种异步的方法,还是事件驱动的。你可以通过函数有效地操作,并且可以将它们作为一等函数传递,并且可以使用闭包(匿名函数),使这种方法成为JavaScript中最重要的编程方法。无论如何,我更喜欢r.on("data",function(chunk)),在那里你可以直接处理读取的数据。与readable相比,data信号表明从流中已经读取了某些内容,而不是可以读取某些内容。这也是io的首选方式。 - ikrabbe
2
@BigMan73是正确的 - 这将在正文字符串末尾添加一个null。请查看他的答案。 - Alexander Flenniken

4
从官方文档中 https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction
let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // at this point, `body` has the entire request body stored in it as a string
});

如果你想使用await,你可以将它转换成一个promise,就像这样:
// how to call function:
const body = await getBody(request);

// function:
function getBody(request) {
  return new Promise((resolve) => {
    const bodyParts = [];
    let body;
    request.on('data', (chunk) => {
      bodyParts.push(chunk);
    }).on('end', () => {
      body = Buffer.concat(bodyParts).toString();
      resolve(body)
    });
  });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接