4

I need to get the raw post data for a specific endpoint in a node/express app. I do:

app.use('/paypal/ipn',function(req, res, next) {
    var postData='';

    req.on('data', function(chunk) { 
        postData += chunk;
    });

    req.on('end', function() {
        req.rawBody = postData;
        console.log('ended buffering. result: ' + req.rawBody);
        next();
    });
});

What happens is that I get the console.log output in the console and then nothing happens. After a minute or so I see the server returns 200 - probably a timeout. It's like the next() command never executes, or executes and stales.

When I comment out everything, and simply call next():

app.use('/paypal/ipn',function(req, res, next) {
    /*
    var postData='';

    req.on('data', function(chunk) { 
        postData += chunk;
    });

    req.on('end', function() {
        req.rawBody = postData;
        console.log('ended buffering. result: ' + req.rawBody);
        next();
    });
    */
    next();
});

Everything works, that is the endpoint is called (of course the request doesn't contain the rawBody).

So it seems like I'm doing something wrong the way I buffer the rawBody? Something that causes next() not to work?

shaharsol
  • 991
  • 2
  • 10
  • 31
  • You can always debug it with node's built-in debugger. Run your app as `$ node debug app.js` after you place a `debugger` statement right after your `console.log()`. Step into `next()` and follow it down the rabbit hole. – Thalis K. Feb 24 '14 at 21:47
  • given the route you provide above, there is no next route to call.. try adding after that route something simply such as `function(req,res){ res.json(200,req.rawBody);}` – Gntem Feb 25 '14 at 08:26
  • Further down in app.js I have this line: app.post('/paypal/ipn',paypal.ipn(db)); When I comment out everything and simply calls next(); then this is the code that executes. I don't understand what makes my code (when not commented out) to make next() think it has nowhere to go to – shaharsol Feb 25 '14 at 12:52

4 Answers4

6

Call next() without waiting for 'end', to prevent bodyParser and your code from interfering.

app.use(function(req, res, next) {
  req.rawBody = '';

  req.on('data', function(chunk) { 
    req.rawBody += chunk;
  });

  next();
});
app.use(express.bodyParser());

Kudos to https://stackoverflow.com/a/21222540/1891397

Community
  • 1
  • 1
Oren Solomianik
  • 385
  • 3
  • 8
1

I had similar problem, checkout this code (rawBody):

/*
for some very strange reason, while a IE8/IE9 use a XDomain for CORS requests, express.js bodyParser fail to parse
*/
app.use(function(req, res, next) {
    if(req.method !== 'POST') {
        next();
        return;
    }
    var data = '';
    req.setEncoding('utf8');
    req.on('data', function(chunk) { 
        data += chunk;
    });
    req.on('end', function() {
        req.rawBody = data;
        req.failSafeBody = queryParser(data);
        next();
    });
});
//se above
//app.use(express.bodyParser());
app.use(function(req, res, next){
    if(req.method === 'POST' && (!req.body || Object.keys(req.body).length<1) ) {
        req.body = req.failSafeBody;
    }
    next();
});
app.use(express.methodOverride());
h0x91B
  • 1,211
  • 15
  • 19
1

A simple change would show why next isn't run:

app.use('/paypal/ipn',function(req, res, next) {
  var postData='';

  req.on('data', function(chunk) { 
    postData += chunk;
  });

  req.on('end', function() {
    req.rawBody = postData;
    console.log('ended buffering. result: ' + req.rawBody);
    console.log(next);
  });
});

It is likely that the next callback simply doesn't exist and so fails silently. If it DOES exist, then you just have to enter it and debug it line by line.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
SirDemon
  • 1,758
  • 15
  • 24
  • Oh, I did that. And it exists. And I tried to debug it is just that I'm getting into node internals that I don't understand -- got as deep as debugging node.js file itself... I don't think it will get me anywhere as I am not such familiar with node source code. – shaharsol Feb 25 '14 at 12:50
0

I got same troubles like that. So, after no good answer found on google, I spent more hours to fix it.

You should be noticed that on middleware of connect node_module, it completed reading data on stream when you call express.urlencoded(), so I find a best way to fix that problems:

app.use(express.urlencoded());
app.use(function(req, res, next){
    if (req.method !== 'POST' || JSON.stringify(req.body) !== JSON.stringify({})){
        next()
        return
    }
    var data = ''
    req.on('data', function(chunk){
        data += chunk
    })
    req.on('end', function(){
        req.rawBody = data
        next()
    })
})

How it works? First, we completed reading stream by calling urlencoded() and we got req.body by function returned.

After that, in hack function rawBody, we check if method is not 'POST' (GET ?) or req.body is not equals {} that means urlencoded() parsed data sucessfully, we dont need to do anything (or if you still need rawBody at this point, you simply join() req.body with '&') so we simple call next() and return for breaking function

(sr my bad English, I really want to share this exp, I think you will need it like me ;) )

JSON3
  • 1
  • 1