Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access the raw body of the request before bodyparser?

I am writing a custom middleware that generates a cryptographic signature of every request (it is very similiar to the authentication mechanism used by AWS API v4). In order for this signature to be correctly generated, I must fetch the entire raw body of the HTTP request.

I am also using BodyParser, which is registered after my custom middleware.

My custom middleware can be represented like this:

// libs/simplifiedSignatureCheckerMiddleware.js

module.exports = function (req, res, next){

// simple and fast hashing stuff

var payload = '';
req.on('data', function(chunk) { payload += chunk }, null);
req.on('end', function(){

    // hmac stuff

    console.log(payload);

    var ok = true; // ...

    if(ok)
        next();
    else
        next("Bad")
});

}

This is how I use it on the server.

// simpleServer.js

// BASE SETUP
// =============================================================================
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var jsonStream = require('express-jsonstream');
var nconf = require('nconf');
var https = require('https');
var fs = require('fs');

// load configurations
nconf.argv().env();
nconf.file({file: 'config.json'});

app.use(require('./libs/simplifiedSignatureCheckerMiddleware'));

// configure app to use bodyParser()
// this will let us get the data from a POST
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(jsonStream());

// ROUTES FOR API
// =============================================================================
var router = express.Router();

router.post('/api/', function (req, res) {
    var param1 = req.body.param1 || "";
    var param2 = req.body.param2 || "";

    res.json({message: 'welcome', one: param1, two: param2 });
});
// REGISTER ROUTES
app.use(router);

// START THE SERVER
// =============================================================================

https.createServer({
    key: fs.readFileSync('./key.pem'),
    cert: fs.readFileSync('./cert.pem')
}, app).listen(nconf.get('http:port'));

console.log("APIs listening on port " + nconf.get('http:port'));

As you can verify, the raw body is written successfully to the console by the middleware, BUT the request will never be processed by the registered route and the connection hangs forever.

Do you have any clue on how to solve this problem?

Thanks in advance.

like image 349
Emanuele Casadio Avatar asked May 12 '15 13:05

Emanuele Casadio


1 Answers

Ok, since the only feasible way to solve this problem seems to be by modifying the original source code of bodyParser, I have forked it.

https://github.com/emanuelecasadio/body-parser-rawbody

This fork exposes the raw body of the request as a field named rawBody. As you can see, there is only ONE extra line of code.

You can install it by using npm install body-parser-rawbody.

EDIT

Another option is to use the bodyParser like this, as noted by dougwilson here: https://github.com/expressjs/body-parser/issues/83#issuecomment-80784100

app.use(bodyParser.json({verify:function(req,res,buf){req.rawBody=buf}}))

I haven't personally tried this option and I do not know if it works.

like image 52
Emanuele Casadio Avatar answered Nov 01 '22 12:11

Emanuele Casadio