Post body empty

Showing 1-7 of 7 messages
Post body empty Stanislav Pogrebnyak 6/2/12 5:40 AM
Hi! 

I'm trying to build small and simple mmonit clone application with node.js, thats my first application in node and express and I've faced an issue with post data.

Application code:

var 
  express  = require('express'), 
  http     = require('http'),
  routes   = require('./routes');

var app = express.createServer();

app.configure(function(){
  app.set('port', process.env.PORT || 3001);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

app.post('/collector', function(req, res){
  console.log( req.body ) ;
  res.send("OK");
});

http.createServer(app).listen(app.get('port'), function() {
  console.log("Express server listening on port " + app.get('port'));
});


And the result in console is:

POST /collector 200 1ms
{}

When i'm redirecting the monit to rails application in console i can see the parsed params those are:

{"monit"=>{"services"=>{"service"=>[{"children"=>"1", "ppid"=>"1", "cpu"=>{"percenttotal"=>"0.0", "percent"=>"0.0"}, "monitormode"=>"0", "type"=>"3", "port"=>{"type"=>"TCP", "portnumber"=>"80", "protocol"=>"DEFAULT", "hostname"=>"127.0.0.1", "request"=>nil, "responsetime"=>"0.000"}, "status_hint"=>"0", "status"=>"0", "collected_sec"=>"1338639012", "uptime"=>"9867", "monitor"=>"1", "pid"=>"18574", "name"=>"nginx", "pendingaction"=>"0", "collected_usec"=>"429327", "memory"=>{"kilobytetotal"=>"2976", "percenttotal"=>"0.0", "percent"=>"0.0", "kilobyte"=>"1028"}}, {"system"=>{"cpu"=>{"system"=>"0.3", "user"=>"1.4", "wait"=>"0.0"}, "swap"=>{"percent"=>"0.0", "kilobyte"=>"52"}, "load"=>{"avg05"=>"0.60", "avg01"=>"0.70", "avg15"=>"0.54"}, "memory"=>{"percent"=>"43.6", "kilobyte"=>"2644604"}}, "monitormode"=>"0", "type"=>"5", "status_hint"=>"0", "status"=>"0", "collected_sec"=>"1338639012", "monitor"=>"1", "name"=>"system_cthulhu-laptop", "pendingaction"=>"0", "collected_usec"=>"429327"}]}, "version"=>"5.3.2", "server"=>{"startdelay"=>"0", "httpd"=>{"address"=>"localhost", "port"=>"3002", "ssl"=>"0"}, "uptime"=>"230", "controlfile"=>"/etc/monit/monitrc", "localhostname"=>"cthulhu-laptop", "poll"=>"5"}, "platform"=>{"cpu"=>"8", "release"=>"3.2.0-24-generic", "version"=>"#39-Ubuntu SMP Mon May 21 16:52:17 UTC 2012", "swap"=>"6236156", "machine"=>"x86_64", "name"=>"Linux", "memory"=>"6060628"}, "incarnation"=>"1338638782", "servicegroups"=>nil, "id"=>"357366846a5b24d5d4d740a42a62af48"}}

What do i do wrong?

Thanks for help.
Re: Post body empty Didier Colens 6/7/12 2:46 AM
monit sends the data as with a content-type of "text/xml" which is not supported by bodyParser (it supports 'application/json', 'application/x-www-form-urlencoded' and 'multipart/form-data') and therefore the req.body is not populated.

there used to be a req.rawBody, but it is not there anymore, so you could write a middleware to parse the text/xml sent by monit inspired by the 'application/json' parser, something like:


var utils = require('connect').utils
  , xml2js = require('xml2js')
  , parser = new xml2js.Parser()
  ;

function xmlBodyParser(req, res, next) {
if (req._body) return next();
req.body = req.body || {};
// ignore GET
if ('GET' == req.method || 'HEAD' == req.method) return next();
// check Content-Type
if ('text/xml' != utils.mime(req)) return next();
// flag as parsed
req._body = true;
// parse
var buf = '';
req.setEncoding('utf8');
req.on('data', function(chunk){ buf += chunk });
req.on('end', function(){  
parser.parseString(buf, function(err, json) {
if (err) {
err.status = 400;
next(err);
} else {
req.body = json;
next();
}
});
});
}

could do and then add use it with "app.use (xmlBodyParser);".

Did

Re: Post body empty Didier Colens 6/7/12 2:54 AM
Hi,

that's because monit sends a post with "text/xml" content which is not supported by bodyParser, so your req.body remains empty. Express used to have a req.rawBody but it is deprecated. So the only solution is to write a middleware to parse the "text/xml" request. Taking the bodyParser json parser as an example it could be:

var utils = require('connect').utils
  , fs = require('fs')
  , xml2js = require('xml2js')
  ;

function xmlBodyParser(req, res, next) {
if (req._body) return next();
req.body = req.body || {};
// ignore GET
if ('GET' == req.method || 'HEAD' == req.method) return next();
// check Content-Type
if ('text/xml' != utils.mime(req)) return next();
// flag as parsed
req._body = true;
// parse
var buf = '';
req.setEncoding('utf8');
req.on('data', function(chunk){ buf += chunk });
req.on('end', function(){  
parser.parseString(buf, function(err, json) {
if (err) {
err.status = 400;
next(err);
} else {
req.body = json;
next();
}
});
});
}

app.use (xmlBodyParser);


Did

On Saturday, June 2, 2012 2:40:24 PM UTC+2, Stanislav Pogrebnyak wrote:
Re: Post body empty Stanislav Pogrebnyak 6/7/12 2:56 PM
Yes, indeed, thanx. Works like a charm.

суббота, 2 июня 2012 г., 15:40:24 UTC+3 пользователь Stanislav Pogrebnyak написал:
Re: Post body empty Bill 12/24/12 10:54 AM
Thanks for providing this...I'm using it too and while it's not erroring out anymore, req.body is empty...any suggestions?
Re: Post body empty Bill 12/26/12 11:53 AM
Here's what I've got:

exports.addXMLTicket = function(req, res) {
console.log(req.body);
var ticket = req.body;
    console.log('Adding ticket: ' + JSON.stringify(ticket));
    db.collection('tickets', function(err, collection) {
        collection.insert(ticket, {safe:true}, function(err, result) {
            if (err) {
                res.send({'error':'An error has occurred'});
            } else {
                console.log('Success: ' + JSON.stringify(result[0]));
                res.send(result[0]);
            }
        });
    });
}
Re: Post body empty Arush Sehgal 1/2/13 10:02 AM
I've created a module out of this solution and modified it slightly to work with express.