NodeJS and body-parser - node.js

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'})

Related

Express serving static file: can't set headers after they are send

I am using the express.static built-in middleware function to serve static files, but the console prints the error: Can't set headers after they are sent.
here is my code, i don't know what is wrong with this
'use strict';
let path = require('path');
let express = require('express');
let bodyParser = require('body-parser');
let mongoose = require('mongoose');
let formidable = require('express-formidable');
let routes = require('./routes');
let app = express();
let port = process.env.PORT || 3000;
let db = mongoose.connect('mongodb://localhost:27017/old-driver');
// deal with img post
app.use(formidable({
uploadDir: path.join(__dirname, 'upload'),
keepExtensions: true
}));
app.use(bodyParser.urlencoded({extended: true }));
app.use(bodyParser.json());
// access-control
app.all('*', (req, res, next) => {
res.set("Access-Control-Allow-Origin", "*");
res.set("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
res.set("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.set("X-Powered-By",' 3.2.1')
res.type("application/json");
res.type("jpg");
next();
});
// set assets path, GET /assets/demo.png
app.use('/assets', express.static('upload'));
routes(app);
app.listen(port);
the route middleware method:
getAllTeachers: (req, res) => {
Teacher.find({}, (err, teacher) => {
if (err) {
res.send(err);
} else {
res.json(teacher);
}
});
},
Even if I remove the access-contol code as shown below, still get error
let db = mongoose.connect('mongodb://localhost:27017/old-driver');
// deal with img post
app.use(formidable({
uploadDir: path.join(__dirname, 'upload'),
keepExtensions: true
}));
app.use(bodyParser.urlencoded({extended: true }));
app.use(bodyParser.json());
// set assets path, GET /assets/demo.png
app.use('/assets', express.static('upload'));
routes(app);
app.listen(port);
when I request 2 existing jpg file, I also get 404 error in one jpg file
404 screenshot
To solve this you need to use app.use function instead of app.all for mounting your middleware function. app.use adds the middleware function to middleware stack ensuring that they are executed in same order at which they are added.
So you need to do this :
app.use((req, res, next) => { //change app.all to app.use here and remove '*', i.e. the first parameter part
res.set("Access-Control-Allow-Origin", "*");
res.set("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
res.set("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.set("X-Powered-By",' 3.2.1')
res.type("application/json");
res.type("jpg");
next();
});
EDIT:
As you told in comments the above method doesn't work so what you can do is use the setHeaders method of express.static method to set headers before file is served like this :
app.use('/assets', express.static('upload', {
setHeaders: function(res, path) {
res.set("Access-Control-Allow-Origin", "*");
res.set("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
res.set("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.set("X-Powered-By",' 3.2.1')
res.type("application/json");
res.type("jpg");
}
}));
Put this static file serving middleware method above the app.use so that app.use method for setting headers is not called hence the headers won't be set again.

request body undefined in node express

In node express when I try to access the post value from the form it shows request body undefined error.
Here is my code,
http.createServer(function(req, res) {
var hostname = req.headers.host.split(":")[0];
var pathname = url.parse(req.url).pathname;
if (pathname==="/login" && req.method ==="POST") {
console.log("request Header==>" + req.body.username );
}).listen(9000, function() {
console.log('http://localhost:9000');
});
Please any one help me to find why the request body shows undefined.
Enable body-parser middleware first
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
app.use(function (req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
res.end(JSON.stringify(req.body, null, 2))
})
If you're not using express for the web server and just plain http. Use the body module.

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");

How to get post params in app.post

I am developing nodejs project. Where I am using ejs with the help of express-helpers module to generate view template html.
in server.js file I have written below code
var http = require('http');
var path = require('path');
var async = require('async');
var socketio = require('socket.io');
var express = require('express');
var app = express();
var helpers = require('express-helpers')
helpers(app);
var server = http.Server(app);
server.listen(process.env.PORT || 3000, process.env.IP || "0.0.0.0", function(){
var addr = server.address();
console.log("Chat server listening at", addr.address + ":" + addr.port);
});
app.use(express.static(__dirname + '/public'));
app.set('views', __dirname + '/public/views');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
//app.use(express.static(__dirname + '/client'));
app.use(express.static(path.join(__dirname, '/client')));
// respond with "index.html" when a GET request is made to the homepage
app.get('/', function(req, res) {
res.render('index.html');
});
app.get('/demo', function (req, res) {
res.render('demo.ejs');
});
app.post('/demo', function (req, res) {
console.log(res.body)
});
I want to know that in app.post how should id get post params
app.post('/demo', function (req, res) {
console.log(res.body)
});
I have tried console.log(req.body) but giving as undefined
Also tried console.log(res.body) but giving as undefined
Let me know how should I implement it?
you should use a middleware such as body-parser
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.post('/demo', function (req, res) {
console.log(req.body)
});
Use the body-parser middleware. First, you need to install it using npm install body-parser. And then use it in your application like this
var bodyParser = require('body-parser');
.....
// For Content-Type application/json
app.use(bodyParser.json());
// For x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
....
app.post('/demo', function (req, res) {
console.log(req.body);
});

Get rawBody in express

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.

Resources