NodeJS server crash after save data to mongoDB - javascript

I wrote a script which save an object to a MongoDB database using mongoose. The object is correctly save to the database, but the server crashes right after, throwing me the following error message: catch(err) { process.nextTick(function() { throw err}); }
Here's a part of my code:
users.js
var User = require('../models/user');
router.post('/register', function(req, res, next) {
[...]
// checks for errors
var errors = req.validationErrors();
if (errors) {
res.render('register', {
errors: errors,
[...]
})
} else {
var newUser = new User({
[...]
});
// Create user
User.createUser(newUser, function(err, user) {
if (error) {
throw err;
};
console.log(user);
});
[...]
}
});
module.exports = router;
user.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/nodeauth');
// User Schema
var UserSchema = mongoose.Schema({
[...]
});
var User = module.exports = mongoose.model('User', UserSchema);
module.exports.createUser = function(newUser, callback) {
newUser.save(callback);
}
apps.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var passport = require('passport');
var localStrategy = require('passport-local').Strategy;
var bodyParser = require('body-parser');
var multer = require('multer');
var flash = require('connect-flash');
var mongo = require('mongodb');
var mongoose = require('mongoose');
var db = mongoose.connection;
var expressValidator = require('express-validator');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// handle file uploads
app.use(multer({dest:'./uploads'}).single('singleInputFileName'));
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// handle express session
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
// passport
app.use(passport.initialize());
app.use(passport.session());
// validator
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param : formParam,
msg : msg,
value : value
};
}
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// connect flash
app.use(flash());
app.use(function (req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;

You shouldn't throw error you should return it in handler to let clients know if there is a database error creating the user. Only throw when caller can catch error, async code cannot be caught easily. Promises enable throwing errors but not callbacks.

Related

Router returns 404 in Express.js

I'm currently learning and a newbie to Node.js. I'm trying to build a simple REST API and currently getting an error 404 when try post to a particular route in postman to test if data has successfully been sent to Mongo db. I'm sure what i'm missing. I have double checked all my routes and they seem fine. It works when i make a get request and falls through when i make a post request.
This is my app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var Developer = require('./models/developers');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true}));
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use('/', indexRouter);
app.use('/users', usersRouter);
// Connect to DB
mongoose.connect('mongodb://127.0.0.1:27017');
// API Routes
var router = express.Router();
// Routes will be prefixed with /api
app.use('/api', router);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
// Test Route
router.get('/', function (req, res) {
res.json({message: 'Welcome to my simple API!'});
});
router.route('/developers')
.post(function (req, res) {
var developer = new Developer(); // New instance of sa developer
developer.firstName = req.body.firstName;
developer.lastName = req.body.lastName;
developer.jobTitle = req.body.jobTitle;
developer.save(function (err) {
if (err) {
res.send(err);
} else {
res.json('Developer was successfully fetched');
}
});
})
.get(function (req, res) {
Developer.find(function (err, developers) {
if (err) {
res.send(err);
} else
res.json(developers);
});
});
router.route('/developer/:developer_id')
.get(function (req, res) {
Developer.findById(res.params.developer_id, function (err, developer) {
if (err) {
res.send(err);
}
res.json(developer);
});
});
router.route('/developer/firstName/:firstName')
.get(function (req, res) {
Developer.find({firstName:res.params.firstName}, function (err, developer) {
if (err) {
res.send(err);
}
res.json(developer);
});
});
My model is developer.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var DevelopersSchema = new Schema({
firstName: String,
lastName: String,
jobTitle: String
});
module.exports = mongoose.model('Developers', DevelopersSchema);
To connect the database, instead of
mongoose.connect('mongodb://127.0.0.1:27017');
Use,
mongoose.connect('mongodb://127.0.0.1:27017/yourDatabaseName');
Check the doc.
Mongoose database connection require a database name in connect() method.
Your final app.js should be like,
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var Developer = require('./models/developers');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true}));
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use('/', indexRouter);
app.use('/users', usersRouter);
// Connect to DB
mongoose.connect('mongodb://127.0.0.1:27017/my_unique_data_base_name');
// API Routes
var router = express.Router();
// Routes will be prefixed with /api
app.use('/api', router);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
// Test Route
router.get('/', function (req, res) {
res.json({message: 'Welcome to my simple API!'});
});
router.route('/developers')
.post(function (req, res) {
var developer = new Developer(); // New instance of sa developer
developer.firstName = req.body.firstName;
developer.lastName = req.body.lastName;
developer.jobTitle = req.body.jobTitle;
developer.save(function (err) {
if (err) {
res.send(err);
} else {
res.json('Developer was successfully fetched');
}
});
})
.get(function (req, res) {
Developer.find(function (err, developers) {
if (err) {
res.send(err);
} else
res.json(developers);
});
});
router.route('/developer/:developer_id')
.get(function (req, res) {
Developer.findById(res.params.developer_id, function (err, developer) {
if (err) {
res.send(err);
}
res.json(developer);
});
});
router.route('/developer/firstName/:firstName')
.get(function (req, res) {
Developer.find({firstName:res.params.firstName}, function (err, developer) {
if (err) {
res.send(err);
}
res.json(developer);
});
});
if I'm correct, the line of app.use('/api', router); does nothing.
When coming a request for /api endpoint, a response should be sent at the end of operations. The code pass the request to router. And router does nothing.
Then if createError(404) method calls res.send() or res.end() methods
you should move the use() method to the bottom of your code page:
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
Because at every single time it works before the other routes.
IMHO, using a standard coding style make more readable the program-flow.
Good luck..

How to access app.locals variable in handlebars

app.js
var debug = require('debug');
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
javvar mongoose = require('mongoose');
var session = require('express-session');
var db = require('./dbconn');
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log('we are connected!');
});
var index = require('./routes/index');
var users =
require('./routes/users');
var signup = require('./routes/signup');
var login = require('./routes/login');
var adreqform =
require('./routes/adreqform') var dashboard =
require('./routes/dashboard')
var app = express();
// view engine setup app.set('views', path.join(__dirname, 'views'));
app.engine('hbs', exphbs({
extname: '.hbs',
defaultLayout: 'layout'
}));
app.set('view engine', 'hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname,
'public')));
app.use(session({
secret: 'gh jewellery',
resave: true,
saveUninitialized: false
}));
app.use(function(req, res, next) {
app.locals.currentUser = req.session.user;
next();
});
app.use('/', index);
app.use('/users', users);
app.use('/dashboard',
dashboard);
app.use('/signup', signup);
app.use('/login', login);
app.use('/adreqform', adreqform);
// catch 404 and forward to error handler app.use(function (req, res,
next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler // will print stacktrace if
(app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler // no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
app.set('port', process.env.PORT || 3000);
module.exports = app;
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
Notice I assign app.locals.currentUser = req.session.user; above and req.session.user gets set when my route /login is hit and here is it's code.
login.js
var express = require('express');
var router = express.Router();
var User = require('../models/user.model.js');
var app = require('../app');
/* GET signup page. */
router.get('/', function(req, res, next) {
res.render('login');
});
router.post('/', function(req, res, next) {
User.findOne({
email: req.body.email
}, function(err, user) {
var logged = false;
if (err) {
console.log(err);
} else if (!user) {
res.render('login', {
errnoacc: 'User does not exist! Please register.'
})
} else if (user && req.body.password == user.password) {
req.session.user = user;
res.render('dashboard');
} else {
res.render('login', {
errpass: 'Password does not match. Please try again!'
});
}
});
next();
});
module.exports = router;
In the above code when POST is hit, I assign req.session.user = user; if all is good I render the dashboard view, there are a layout.hbs which has navbar where I want to use app.locals.currentUser to show currentUser object.
Using in my layouts.hbs {{currentUser.username}} doesn't work.
I am new to expressjs development so I know I am missing something.
app.locals holds settings for all application, if you app gets more than one user it will overwrite the information.
app.use(function(req, res, next) {
app.locals.currentUser = req.session.user;
next();
});
You may use res.locals:
app.use(function(req, res, next){
res.locals.user = req.user;
res.locals.authenticated = ! req.user.anonymous;
next();
});
Then you can access in handlebar like:
p #{user.userName}

404 error in Node.js when doing app.get with postgres as Db

I am learning Node.js through a tutorial to build a simple API.
I have my own postgres db and I am trying to retrieve a table and not use the sample db/dummy db in the tutorial. I am following everything in the tutorial, only thing is I am using my own db and getting 404 not found error.
My Index.js
var express = require('express');
var router = express.Router();
var db = require('../queries');
router.get('/api/preference', function(req,res){ res.send('hi'); })
module.exports = router;
Queries.js
var promise = require('bluebird');
var options ={
//Initialization options
promiseLib : promise
};
var pgp = require('pg-promise')(options);
var db = pgp({
host: 'localhost',
port: 5432,
database: 'pmc',
user: 'tarun',
password: 'pes'
});
var connectionstring = 'postgres://tarun:pes#localhost:5432/pmc';
var db = pgp(connectionstring);
//add query funtions
module.exports = {
getAllPreference : getAllPreference
};
function getAllPreference(req,res,next){
db.any('select * from core.preferences')
.then(function(data){
res.status(200)
.json({
status : 'success',
data : data,
message: 'Retrieved ALL preferences'
});
})
.catch(function (err) {
return next(err);
});
}
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
Error
Error: Not Found
at D:\node-postgress-promises\app.js:32:13
at Layer.handle [as handle_request] (D:\node-postgress-promises\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (D:\node-postgress-promises\node_modules\express\lib\router\index.js:317:13)
at D:\node-postgress-promises\node_modules\express\lib\router\index.js:284:7
at Function.process_params (D:\node-postgress-promises\node_modules\express\lib\router\index.js:335:12)
at next (D:\node-postgress-promises\node_modules\express\lib\router\index.js:275:10)
at D:\node-postgress-promises\node_modules\express\lib\router\index.js:635:15
at next (D:\node-postgress-promises\node_modules\express\lib\router\index.js:260:14)
at Function.handle (D:\node-postgress-promises\node_modules\express\lib\router\index.js:174:3)
at router (D:\node-postgress-promises\node_modules\express\lib\router\index.js:47:12)
Blockquote
Change this portion of code as follow
exports.getAllPreference = function(req,res,next){
console.log('h');
db.any('select * from core.preferences')
.then(function(data){
res.status(200)
.json({
status : 'success',
data : data,
message: 'Retrieved ALL preferences'
});
})
.catch(function (err) {
next(err);
});
}
Remove below code in this file
module.exports = {
getAllPreference= getAllPreference
}
Change your index.js file Remove below lines
module.exports = {
getAllPreference: getAllPreference
};
function getAllPreference(req, res, next) {};
And uncomment
module.exports = router;
Add below code for testing purpose. in index.js file
router.get('/api/preference', function(req,res){
res.send('hi');
};

Undefined while sending post nodejs

I try to send a form with data in my nodejs app but I get "undefined" I am not sure does it matter but in console first I see "undefined", then POST. I have tried some "fixes" from the Internet like adding "type:'application/*+json', inflate: false" to app.use(bodyParser.json...) but nothing worked for me...
Undefined
POST /users/register 200 32.777 ms - 2346
this is my routes/users.js file:
var express = require('express');
var router = express.Router();
router.get('/register', function(req, res, next) {
res.render('register', {
'title': 'Register'
});
});
router.post('/register', function(req, res, next) {
console.log(req.body.name);
});
module.exports = router;
heres my jade file
form(method='post', action='/users/register', role='form')
.form-group
label Name
input.form-control(type='text', name='name', placeholder='Enter Name')
input.btn.btn-default(name='submit', type='submit', value='Register')
and app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var expressValidator = require('express-validator');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var bodyParser = require('body-parser');
var flash = require('connect-flash');
var mongo = require('mongodb');
var mongoose = require('mongoose');
var db = mongoose.connection;
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(bodyParser.json({ type: 'application/*+json' }));
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.'),
root = namespace.shift(),
formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param: formParam,
msg: msg,
value: value
};
}
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(flash());
app.use(function(req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
app.use('/', routes);
app.use('/users', users);
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
Routing works fine what show setting up a title to "Register", but I have problems with sending post :/
You're configuring body-parser to only accept JSON request bodies, but your form is submitted in URL-encoded format (application/x-www-form-urlencoded).
For that, you need to add the correct parser:
app.use(bodyParser.urlencoded({ extended : true }));
More information, also on the meaning of extended : true, here.

Express Js: Router.use() Requires Middleware function

I am developing an application in Express Js. When I try to run the application I get this error:
My app.js file is like this:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
var server = app.listen(3000, function() {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
module.exports = router;
My index.js is like this:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function (req, res, next) {
res.render('index', {title: 'Polls'});
});
router.get("/list", function (req, res, next) {
Poll.find({}, 'question', function (error, polls) {
res.json(polls);
});
});
router.get("/poll", function (req, res, next) {
var pollId = req.params.id;
// Find the poll by its ID, use lean as we won't be changing it
Poll.findById(pollId, '', {lean: true}, function (err, poll) {
if (poll) {
var userVoted = false,
userChoice,
totalVotes = 0;
// Loop through poll choices to determine if user has voted
// on this poll, and if so, what they selected
for (c in poll.choices) {
var choice = poll.choices[c];
for (v in choice.votes) {
var vote = choice.votes[v];
totalVotes++;
if (vote.ip === (req.header('x-forwarded-for') || req.ip)) {
userVoted = true;
userChoice = {_id: choice._id, text: choice.text};
}
}
}
// Attach info about user's past voting on this poll
poll.userVoted = userVoted;
poll.userChoice = userChoice;
poll.totalVotes = totalVotes;
res.json(poll);
} else {
res.json({error: true});
}
});
});
router.get("/create", function (req, res, next) {
var reqBody = req.body,
// Filter out choices with empty text
choices = reqBody.choices.filter(function (v) {
return v.text != '';
}),
// Build up poll object to save
pollObj = {question: reqBody.question, choices: choices};
// Create poll model from built up poll object
var poll = new Poll(pollObj);
// Save poll to DB
poll.save(function (err, doc) {
if (err || !doc) {
throw 'Error';
} else {
res.json(doc);
}
});
});
module.exports = router;
And user.js is this:
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
I tried to find my solution on SO, but couldn't. Feel free to tell me if i need to provide any other file. Any help?
You should define routes in your index.js like you do in user.js.
app.use('/', routes) in your code expects routes to be an instance of a Router, but you're exporting an object with functions instead of that.
So your index.js file should have the following structure:
var express = require('express');
var router = express.Router();
router.get("/", function (req, res) {
res.render('index');
});
router.get("/list", function(req, res) {/*list implementation*/});
....
module.exports = router;

Categories