Get rawBody in express - node.js

Hello I am trying to retrieve something from the post, and need the rawBody property from the incoming request. How can I retrieve it??
I tried using express.bodyParser() and in my post handler, I was looking for req.rawBody, and it was undefined.
I even tried it with connect.bodyParser(), but I still have no luck with it. I am getting undefined for rawBody.
I was reading on the stackoverflow site saying that they had removed the rawBody functionality, but mentioned that it is a quick fix to add it to our own middleware file. I am a newbie, so I do not have a clue as to how to achieve this. Below is my code snippet.
/**
* Module dependencies.
*/
var express = require('express')
, connect = require('connect')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
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(connect.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);
/**custom stuff**/
app.post('/upload',function(req, res){
console.log(req.header('Content-Type'));
console.log(req.header('Host'));
console.log(req.header('User-Agent'));
console.log(req.rawBody);
console.log(req.body);
res.send("<h1> Hello the response is "+req.body.username);
});
/** end**/
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
Any help with this is much appreciated.
Thank you.

You can use your own middle ware to do this:
app.use(function(req, res, next){
var data = "";
req.on('data', function(chunk){ data += chunk})
req.on('end', function(){
req.rawBody = data;
next();
})
})
// Your route registration:
app.get('/', function(){// whatever...})
app.post('/test', function(req, res){
console.log(req.rawBody);
res.send("your request raw body is:"+req.rawBody);
})

I'm back again :D. After read the connect.bodyParser I've found something: The bodyParser only parse the data which mime type is one of: application/json, application/x-www-form-urlencoded and multipart/form-data. So I think this is another approach, it's not generally elegant but acceptable: When you try to send raw data to server, change the mime type to something different. As your question it's a string, so I choose text/plain as example:
// if the request's mime type is text/plain, read it as raw data
var myRawParser = function(req, res, next){
req.rawData = '';
if(req.header('content-type') == 'text/plain'){
req.on('data', function(chunk){
req.rawData += chunk;
})
req.on('end', function(){
next();
})
} else {
next();
}
}
// ...
app.use(myRawParser);
app.use(express.bodyParser());
// ...
// Here is my test route:
app.post('/test', function(req, res){
console.log('Mime type is:'+req.header('content-type'));
console.log('Raw data is:'+req.rawData);
console.log('Body via bodyParser is:');
console.dir(req.body);
res.send('Hello!');
})
I've tested it via curl:
$ curl -d 'test=hello' 127.0.0.1:3000/test
// console result:
Mime type is:application/x-www-form-urlencoded
Raw data is:
Body via bodyParser is:
{ test: 'hello' }
and:
$ curl -d 'test=hello' -H 'Content-Type:text/plain' 127.0.0.1:3000/test
// console result:
Mime type is:text/plain
Raw data is:test=hello
Body via bodyParser is:
{}
It's not actually integrate your middle ware to bodyParser, just make them work together.

Building on #Rikky's solution, the way to avoid a race condition in the data event handlers is to continue calling the middleware chain immediately after setting the handlers. Don't wait for req.on('end') to call next(), because that next() call is what allows the json body parser to register its own data and end handlers; if you wait until end is triggered on the request, they'll miss all the relevant events. Instead, use promises:
const process = require('process');
const bodyParser = require('body-parser');
const express = require('express');
function main() {
const app = express();
app.use((req, res, next) => {
req.rawBody = new Promise(resolve => {
buf = '';
req.on('data', x => buf += x);
req.on('end', () => {
resolve(buf);
});
});
next();
});
app.use(bodyParser.json());
app.use('/', async (req, res) => {
console.log('raw body:', await req.rawBody);
console.log('json parsed:', req.body);
res.send('bye\n');
});
app.listen('3000', 'localhost', (e) => {
if (e) {
console.error(e);
process.exit(1);
}
console.log('Listening on localhost:3000');
});
}
main();

The best solution I found is here: https://stackoverflow.com/a/9931478/1768033
Because using
req.on('data', function(chunk){ data += chunk})
somehow shifted the bits of the files I send in multiform-data requests, so they were not valid anymore.

Related

NodeJS and body-parser

I tried to make a golden book width nodeJS. So I use body-parser to get my form's values and it works until I try to verify if my form is empty by this way :
app.post('/', (request, response) => {
if(request.body.message === undefined) {
console.log('Message : ' + request.body.message);
}
When I try to run my server and test my form by pushing informations, the loading of the page is infinite.
Can you help me please ?
Here, the full code :
let express = require('express');
let app = express();
let bodyParser = require('body-parser');
// moteur de template
app.set('view engine','ejs');
// MIDDLEWARE
app.use('/assets', express.static('public'));
app.use(bodyParser.urlencoded({ extended: true }));
// parse application/json
app.use(bodyParser.json());
// ROUTE
app.get('/', (request, response) =>{
response.render('pages/index');
});
app.post('/', (request, response) => {
if(request.body.message === undefined) {
console.log('Message : ' + request.body.message);
}
});
app.listen(8080);
Your request is infinite, because you never finish it.
You can do it by simple
response.end()
in your request handler or if you want to return something to a client, then you can use
response.send({message: 'hello there'})

How to see the content stored in a path?

I wrote the following code:
var express = require('express');
var router = express.Router();
var app = express();
app.put('/data', function(req, res) {
res.send("OK");
});
app.get('/data', function(req, res) {
console.log(); // What to write here?
});
app.listen(4000);
I sent a PUT request by Postman:
Now, I want to ask what I to write inside the brackets of console.log that the code will print the content stored in the http path?
I want to see the JSON
{"name":"John"}
EDIT: I tried the solution shown in this link:
Node.js - get raw request body using Express:
var express = require('express');
var router = express.Router();
var app = express();
var bodyParser = require('body-parser');
app.use(function(req, res, next) {
req.rawBody = '';
req.on('data', function(chunk) {
req.rawBody += chunk;
});
next();
});
app.use(bodyParser());
app.put('/data', function(req, res) {
res.send("OK");
});
app.get('/data', function(req, res) {
console.log(res.rawBody);
res.end();
});
app.listen(4000);
I still didn't get what I expected.

post using restler and node.js is not returning

I am trying to post using restler and return the response to client but response never returns .Below is code I am using and response is just hanging
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var rest = require('restler');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var port = 3001; // can also get it from process.env.PORT
var router = express.Router();
//this is like interceptor for every route to validate all requests, logging for analytics
router.use(function (req, res, next) {
console.log('route intercepted');
next(); // make sure we go to the next routes and don't stop here
});
router.get('/', function(req, res) {
res.json({ message: "welcome to restful node proxy layer to business processes" });
});
router.route('/someroute').post(function(req, res) {
rest.postJson('http://localhost/api/sg', req.body).on('complete', function(data, response) {
console.log(response);
}
).on('error', function(data, response) {
console.log('error');
});
});
app.use('/api', router); //all routes are prefixed with /api
app.listen(port);
console.log("server is running magic happens from here");

Where this undefined in Express.js console is coming from?

Useless middleware for testing purposes:
module.exports = function () {
return function rankick(req, res, next) {
if (Math.random() < 0.5) {
return next('Random kick...');
}
next();
};
};
Injected into a simple express app:
var express = require('express'),
http = require('http'),
path = require('path')
rankick= require('./rankick'),
util = require('util');
var app = express();
app.set('port', process.env.PORT || 8080);
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(express.static(path.join(__dirname, 'public')));
app.use(rankick()); // Using the middleware
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.use(function (req, res, next) {
res.end('Hello World!');
});
http.createServer(app).listen(app.get('port'));
When next() is invoked with the error string, console logs undefined followed by the 500 error:
undefined
GET / 500 28ms
GET / 200 4ms
undefined
GET / 500 5ms
Is it's this line in the errorHandler middleware. Maybe it expects to get a new Error('Random kick..')?
It's been a while since I used to default errorHandler so I am not 100% sure. In case it's not downvote and I'll remove this answer.
You should do
module.exports = function rankick(req, res, next) {
if (Math.random() < 0.5) {
console.log('Random kick...');
}
else
next();
};
Don't use return to pass the function. module.exports is the object that is passed when require is called.
Also next() is supposed to be called if you want to continue processing to next middleware. If you want to stop processing/kick request don't call next()

How can I use director as router in expressjs

I want to use express.js with Flatiron's director (router) and Resourceful (ODM) because I need like the benefits of routing tables and clean multi-db schemas with validation.
The reason why I now completly switch to Flatiron is, is because I think it needs some more time and there is not much doc material.
However, that is the current way I use director in express:
var express = require('express')
, director = require('director');
function hello(){
console.log('Success');
}
var router = new director.http.Router({
'/': {
get: hello
}
});
Unfortunatly this doesn't work and gives me just a "Cannot GET /"
So what's to do?
var express = require('express')
, director = require('director')
, http = require('http');
var app = express();
var hello = function () {
this.res.send(200, 'Hello World!');
};
var router = new director.http.Router({
'/': {
get: hello
}
});
var middleware = function (req, res, next) {
router.dispatch(req, res, function (err) {
if (err == undefined || err) next();
});
};
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.bodyParser());
app.use(middleware);
app.use(express.static(__dirname + '/public'));
});
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
There is a sample app using express, resourceful and director here.
If you have more doubts, you can ask them in our IRC room #nodejitsu on freenode.
First, in order to use director you need to wrap it up as a middleware and pass it to express, like so:
app.use(function (req, res, next) {
router.dispatch(req, res, function (err) {
if (err) {
// handle errors however you like. This one is probably not important.
}
next();
});
};
Aside from that: You don't need director to use resourceful, and express has its own router (so you may not even need/want director).

Resources