61

How can I access raw body of request object given to me by expressjs?

var express = require('./node_modules/express');
var app = express.createServer();
app.post('/', function(req, res)
{
    console.log(req.body); //says 'undefined'
});
app.listen(80);
Andrey Kon
  • 1,009
  • 2
  • 9
  • 17
  • A little most context here would be useful. What type of data are you expecting in the body? Are you trying to read form data, or something more complicated. – loganfsmyth Mar 29 '12 at 07:00
  • 4
    I'm not sure I understand how that impacts on the way that I can get raw body. Let's say that it's just some unknown binary data. – Andrey Kon Mar 29 '12 at 08:18
  • Well for one, I wanted to make sure it wasn't just something you could just use bodyParser for. And if the data was binary then it doesn't make sense to make it a string, so you'd want to aggregate buffers instead. And if it's binary, then you should probably not be aggregating it at all anyway since you should try to immediately pipe the data somewhere. – loganfsmyth Mar 29 '12 at 16:10
  • 4
    Also, you should just be able to do `require('express')`. It will find that module all by itself. – loganfsmyth Mar 29 '12 at 16:12
  • 1
    But what if the data is JSON or XML? – Andrey Kon Mar 29 '12 at 16:51
  • Did you solve this? I need to get the rawBody from the request as well. I have XML data coming in. It sucks that .rawBody was removed from bodyParser. – Tarandeep Gill Mar 29 '12 at 17:29
  • 1
    Tarandeep Gill, you're not gonna believe what I did, lol, but I just modified bodyParser.js source code and brought back that line with rawBody:) So now I have it. Though it seams to me just not right because in this scenario my code invokes bodyParser only to get this rawBody which causes executing a lot of code that I don't need. It's not right from performance point of view. – Andrey Kon Mar 29 '12 at 18:22
  • @Stewe's answer says how to solve this without modifying bodyParser... – loganfsmyth Mar 30 '12 at 03:14

11 Answers11

58

Something like this should work:

var express = require('./node_modules/express');
var app = express.createServer();
app.use (function(req, res, next) {
    var data='';
    req.setEncoding('utf8');
    req.on('data', function(chunk) { 
       data += chunk;
    });

    req.on('end', function() {
        req.body = data;
        next();
    });
});

app.post('/', function(req, res)
{
    console.log(req.body);
});
app.listen(80);
stewe
  • 39,054
  • 13
  • 75
  • 73
43

Using the bodyParser.text() middleware will put the text body in req.body.

app.use(bodyParser.text({type: '*/*'}));

If you want to limit processing the text body to certain routes or post content types, you can do that too.

app.use('/routes/to/save/text/body/*', bodyParser.text({type: 'text/plain'})); //this type is actually the default
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

If you want a raw Buffer, you can use bodyParse.raw().

app.use(bodyParser.raw({type: '*/*'}));

Note: this answer was tested against node v0.12.7, express 4.13.2, and body-parser 1.13.3.

Zugwalt
  • 19,935
  • 20
  • 77
  • 99
  • 2
    This worked for me. I needed to process xml bodies, so I used the following line: `app.use(bodyParser.text({ type: '*/xml' }));` which populated my req.body nicely. – romiem Aug 13 '15 at 15:07
  • 3
    this should be the correct answer. the rest are outdated. – keithics Sep 10 '15 at 11:36
  • `app.use(bodyParser.raw({type: '*/*'}));` if you want the binary data as a Buffer – Bernardo Ramos May 28 '16 at 03:43
  • This answer is still a bit confusing (but I upvoted since it was still helpful). The code example is using `text()` yet you mention using `raw()`. – Matt Browne Jun 22 '17 at 20:30
  • Yeah which is it, `text()` or `raw()`? – korona Jan 24 '18 at 09:33
  • Apologies, `raw()` gives a Buffer, `text()` parses as text and gives a string. For this specific question they'd want `text()`, I'll update the answer. – Zugwalt Jan 25 '18 at 15:14
29

Put the following middleware before bodyParser middleware. It'll collect raw body data in request.rawBody and won't interfere with bodyParser.

app.use(function(req, res, next) {
    var data = '';
    req.setEncoding('utf8');
    req.on('data', function(chunk) { 
        data += chunk;
    });
    req.on('end', function() {
        req.rawBody = data;
        next();
    });
});
app.use(express.bodyParser());
Ben Affleck
  • 11,374
  • 5
  • 50
  • 74
  • 2
    I think that you need to move the next(); call inside req.on('end'.. callback function. – TechplexEngineer Dec 20 '12 at 06:08
  • 1
    As @user1144642 noticed, the original code was correct. This is event based code, if you block the execution and consume all data here then bodyParser will _not_ get any data and will hang forever. next() outside passes control next to bodyParser thus allows it to bind event handler and receive data simultaneously. – Ben Affleck Apr 16 '13 at 09:43
  • I tried the code the way it was originally posted and the req.rawBody variable didn't get filled by the time I wanted to use it. Is there a trick I'm missing? – TechplexEngineer Apr 17 '13 at 11:56
  • @TechplexEngineer req.rawBody will be filled as soon as request received. The idea here is to use it together with bodyParser so they don't interfere. In the same time, bodyParser will not pass control to next() middleware until it consume the request, so any middleware executed after bodyParser will be able to access rawBody. This code is very specific, and functions order here is very important. – Ben Affleck Apr 18 '13 at 10:55
  • The only way I made this work, was by putting the next() inside the 'end' function. I don't really understand what'd be wrong with that. – superiggy Jun 03 '13 at 03:33
  • @hookdump I don't know what was wrong, but this code worked fine for me on old connect and now it doesn't work on the latest version. I fixed the code and put next() inside of end handler. – Ben Affleck Jun 03 '13 at 09:08
  • 1
    For me this only works if I move next() outside of req.on('end', ...) – Tobi Nov 12 '13 at 09:31
  • @Tobi do you use latest express? – Ben Affleck Nov 16 '13 at 14:24
  • `app.use(function(req, res, next) { var req.rawData = ''; req.setEncoding('utf8'); req.on('data', function(chunk) { req.rawData += chunk; }); next(); }); app.use(express.bodyParser()); – Daniele Cruciani Feb 03 '14 at 18:04
  • yes, like Andy said, it real hangs, no data for bodyParser anymore – datdinhquoc Mar 31 '17 at 07:37
22

Default express does not buffer data unless you add middleware to do so. The simple solution is to follow the example in @Stewe's answer below, which would just concatenate all of the data yourself. e.g.

var concat = require('concat-stream');
app.use(function(req, res, next){
  req.pipe(concat(function(data){
    req.body = data;
    next();
  }));
});

The downside of this is that you have now moved all of the POST body content into RAM as a contiguous chunk, which may not be necessary. The other option, which is worth considering but depends on how much data you need to process in the post body, would be to process the data as a stream instead.

For example, with XML you could use an XML parser that supports parsing XML as it comes in as chunks. One such parser would be XML Stream. You do something like this:

var XmlStream = require('xml-stream');

app.post('/', function(req, res) {
  req.setEncoding('utf8');
  var xml = new XmlStream(req);
  xml.on('updateElement: sometag', function(element) {
    // DO some processing on the tag
  });
  xml.on('end', function() {
    res.end();
  });
});
loganfsmyth
  • 135,356
  • 25
  • 296
  • 231
  • Ok, I'll mark your answer as accepted. But this conversation wouldn't have happened if someone hadn't removed the line that saves original body in request object. – Andrey Kon Mar 29 '12 at 19:43
  • 3
    Man, we're here to help, there is no reason to sound so annoyed. Blindly buffering data in doesn't make sense, and doing it yourself is easy if you actually take the time to learn how Node works. Every answer here explains how to do this. – loganfsmyth Mar 30 '12 at 03:17
  • 4
    I'm annoyed by the fact that bodyParser collects body chunks anyway, but doesn't give them to me if they cannot be parsed by bodyParser. That's illogical behaviour. I think that dealing with streams should be hidden from developer when using middleware framework. – Andrey Kon Mar 30 '12 at 06:14
  • 1
    The only chunks bodyParser collects are ones with matching content type allowed by bodyParser, so it should never fail. If it's actually getting parser errors, then you are using the wrong content type. And if you have a custom content type, then adding your own parser middleware for that content-type is what you should do, not hack the bodyParser middleware. – loganfsmyth Mar 30 '12 at 06:26
  • 1
    Since express 4 and body-parser 1.15.2 you can turn `req.body` into a `buffer`. See [this answer](https://stackoverflow.com/a/18710277/344029) – DJDaveMark Sep 26 '18 at 12:21
  • concat is not defined – rofls Feb 12 '20 at 19:12
  • 1
    @rofls Are you missing the `var concat = require('concat-stream');` part of this code? – loganfsmyth Feb 12 '20 at 22:48
15
app.use(bodyParser.json({
    verify: function (req, res, buf, encoding) {
        req.rawBody = buf;
    }
}));
app.use(bodyParser.urlencoded({
    extended: false,
    verify: function (req, res, buf, encoding) {
        req.rawBody = buf;
    }
}));
poordeveloper
  • 2,136
  • 1
  • 21
  • 35
9

So, it seems like Express's bodyParser only parses the incoming data, if the content-type is set to either of the following:

  1. application/x-www-form-urlencoded
  2. application/json
  3. multipart/form-data

In all other cases, it does not even bother reading the data.

You can change line no. 92 of express/node_modules/connect/lib/middleware/bodyParser.js from

} else {
        next();
}

To:

} else {
        var data='';
        req.setEncoding('utf8');
        req.on('data', function(chunk) { 
           data += chunk;
        });

        req.on('end', function() {
            req.rawBody = data;
            next();
        });
}

And then, read req.rawBody from your code.

Tarandeep Gill
  • 1,438
  • 18
  • 32
  • 2
    Modifying connect is really not a great way to do this, though it'll work. As @Stewe's answer shows, you can just as easily add your own middleware, and they you don't have to modify any external libraries. – loganfsmyth Mar 30 '12 at 03:18
7

If you want the body as a buffer:

var rawParser = function(req, res, next) {
    var chunks = [];
    req.on('data', function(chunk) { 
        chunks.push(chunk)
    });
    req.on('end', function() {
        req.body = Buffer.concat(chunks);
        next();
    });
}

or

var rawParser = bodyParser.raw({type: '*/*'});

and then:

app.put('/:name', rawParser, function(req, res) {
  console.log('isBuffer:', Buffer.isBuffer(req.body));
})

or for all routes:

app.use(bodyParser.raw({type: '*/*'}));
Bernardo Ramos
  • 2,789
  • 23
  • 21
5

If you are having trouble with the above solutions interfering with normal post requests, something like this might help:

app.use (function(req, res, next) {
    req.rawBody = '';
    req.setEncoding('utf8');
    req.on('data', function(chunk) { req.rawBody += chunk });
});

More info & source: https://github.com/visionmedia/express/issues/897#issuecomment-3314823

TechplexEngineer
  • 1,630
  • 2
  • 28
  • 43
5

It seems this has become a lot easier now!

The body-parser module is able to parse raw and text data now, which makes the task a one-liner:

app.use(bodyParser.text({type: 'text/plain'}))

OR

app.use(bodyParser.raw({type: 'application/binary'}))

Both lines simply fill the body property, so get the text with res.body. bodyParser.text() will give you the UTF8 string while bodyParser.raw() will give you the raw data.

This is the full code for text/plain data:

var express = require('express')
var bodyParser = require('body-parser')
var app = express()

app.use(bodyParser.text({type: 'text/plain'}))

app.post('/', function (req, res, next) {
    console.log('body:\n' + req.body)

    res.json({msg: 'success!'})

    next()
})

See here for the full documentation: https://www.npmjs.com/package/body-parser

I used express 4.16 and body-parser 1.18

JCH2k
  • 2,661
  • 24
  • 24
3

BE CAREFUL with those other answers as they will not play properly with bodyParser if you're looking to also support json, urlencoded, etc. To get it to work with bodyParser you should condition your handler to only register on the Content-Type header(s) you care about, just like bodyParser itself does.

To get the raw body content of a request with Content-Type: "text/xml" into req.rawBody you can do:

app.use(function(req, res, next) {
  var contentType = req.headers['content-type'] || ''
    , mime = contentType.split(';')[0];

  if (mime != 'text/xml') {
    return next();
  }

  var data = '';
  req.setEncoding('utf8');
  req.on('data', function(chunk) {
    data += chunk;
  });
  req.on('end', function() {
    req.rawBody = data;
    next();
  });
});
nortron
  • 3,853
  • 1
  • 22
  • 26
0

All the answers seems outdated, if anyone still struggling with this then express has built-in Express raw middeware.

This middleware is available in Express v4.16.0 onwards. This is a built-in middleware function in Express. It parses incoming requests with JSON payloads and is based on body-parser.

var express = require("express");
var app = express();

app.use(express.raw({ type: "*/*" }))

app.post("/", (req, res) => {
  // req.body = JSON.parse(req.body); // To parse JSON if needed (in-case)
  console.log(req.body);
  res.end();
});

app.listen(3000, (err) => {
if(!err) console.log("App running!!")
});