I'm experiencing extremely long TTFB on my localhost node/express server.
On average each request's(including static resource) TTFB is around 1s, occasionally up to 7s(I guess this is NOT normal)
What could cause this long TTFB and how to improve?
Could it be my fault for configing express wrong?
Here is my app.js:
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var favicon = require('serve-favicon');
var morgan = require('morgan')
//Router files
var all = require('./api/all');
var admin = require('./api/admin');
var student = require('./api/student');
var teacher = require('./api/teacher');
var course = require('./api/course');
var forum = require('./api/forum');
var group = require('./api/group');
var board = require('./api/board');
// App Setup
var app = express();
// View engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(morgan(':remote-addr [:date[clf]] :user :method :url :status :response-time ms',{
skip: function (req, res) {
//var noUser = (req.AV.user === undefined);
//return noUser;
return true;
}
}));
app.use(favicon(__dirname + '/public/favicon.ico'));
// Load Cloud Code
//app.use(cloud);
//Express Middleware
app.use(methodOverride('_method'))
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(__dirname+'/public'));
//The Route
app.get('/', function(req, res) {
res.send('./public/index.html');
});
//Routers
app.use('/api',all);
app.use('/api/admin',admin);
app.use('/api/student',student);
app.use('/api/teacher',teacher);
app.use('/api/course',course);
app.use('/api/forum',forum);
app.use('/api/group',group);
app.use('/api/board',board);
//404 Handler
app.use(function(req, res, next) {
//console.log("NOT FOUND: "+req.url);
var err = new Error('Not Found');
err.status = 404;
res.render('notfound.jade');
//next(err);
});
// error handlers for different env
if (app.get('env') === 'development') {
console.log("dev env");
app.use(function(err, req, res, next) {
res.status(err.status || 500);
if(res.status===500){
console.log(err);
//console.log(err.stack.split("\n"));
}
res.send({
message: err.message,
error: err
});
});
}
app.use(function(err, req, res, next) {
res.status(err.status || 500);
console.log(err.message);
res.send({
message: err.message,
error: {}
});
});
module.exports = app;
ps:I'm using node 4.0.0 and latest chrome
Related
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}
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.
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.
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;
I have an express v4 server with a route called admin. When the user post a password to the admin route, I want to respond by setting a cookie on the user's browser and sending a small json. For some reason, the server keeps returning error 500 when trying to respond. I'm assuming that this is something to do with the cookie as I can do "res.send()" without any problem. I'm new to express/nodejs so any help is appreciated.
admin.js
var express = require('express');
var router = express.Router();
var cookieParser = require('cookie-parser');
/* POST HANDLER */
router.post('/', function(req, res) {
var on = {'admin' : "on"};
res.cookie(cookie , 'cookie_on').send(on);
});
module.exports = router;
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 routes = require('./routes/index');
var admin = require('./routes/admin');
var blogposts = require('./routes/blogposts');
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('/', routes);
app.use('/admin', admin);
app.use('/blogposts', blogposts);
// 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;
Dumb mistake: Cookie should have been 'cookie'...