Get request body from node.js's http.IncomingMessage

47.9k views Asked by At

I'm trying to implement a simple HTTP endpoint for an application written in node.js. I've created the HTTP server, but now I'm stuck on reading the request content body:

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

Request's method, URL and headers are printed correctly, but r.read() is always NULL. I can say it's not a problem in how the request is made, because content-length header is greater than zero on server side.

Documentation says r is a http.IncomingMessage object that implements the Readable Stream interface, so why it's not working?

3

There are 3 answers

2
lorenzo-s On BEST ANSWER

Ok, I think I've found the solution. The r stream (like everything else in node.js, stupid me...) should be read in an async event-driven way:

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);
0
BigMan73 On

'readable' event is wrong, it incorrectly adds an extra null character to the end of the body string

Processing the stream with chunks using 'data' event:

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); 
0
Welcor On

From the official documentation 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
});

If you want to use await you can convert it to a promise like that:

// 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)
    });
  });
}