Express 3 sessions are always one request behind - node.js

I'm working with the new messages system in express 3 and figured this problem, when handling and validating forms. When submitting an invalid form, the submission fails, but there are no error messages displayed. When submitting it again, the error messages from the last request are shown. I tried using local sessions and Redis sessions, it's always the same. This is default express project:
app.js
var express = require('express')
, routes = require('./routes')
, http = require('http')
, path = require('path');
var app = express();
app.response.message = function(type, msg){
// reference `req.session` via the `this.req` reference
var sess = this.req.session;
// simply add the msg to an array for later
sess.messages = sess.messages || [];
sess.messages.push({type: type, msg: msg});
return this;
};
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req, res, next) {
console.log('req.session', req.session.messages);
var msgs = req.session.messages || [];
res.locals({
messages: msgs,
hasMessages: !! msgs.length
});
req.session.messages = [];
next();
});
});
app.configure('development', function(){
app.use(express.errorHandler());
});
app.get('*', function(req, res, next) {
res.message('hello', req.url);
next();
});
app.get('/', function(req, res) {
res.render('index', { title: 'Express' });
});
app.get('/hello', function(req, res) {
res.render('index', { title: 'Express' });
});
app.get('/world', function(req, res) {
res.render('index', { title: 'Express' });
});
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
index body addition:
<% if (hasMessages) { %>
<ul id="messages">
<% messages.forEach(function(msg){ %>
<li class="<%= msg.type %>"><%= msg.msg %></li>
<% }) %>
</ul>
<% } %>
/ there is no message
/hello shows '/'
/world shows '/hello'
reload shows '/world'
What's the problem here?

If you dont want to defer them you don't need to use sessions at all, that's the whole point in this case is to defer messages for the next render. By the time that middleware populates the "messages" and "hasMessages" it really doesn't have any unless the previous request populated them. This is typically used to defer msgs like "updated user successfully"

Related

nodejs, express and jade: problems with inserts from form to database

when i try to enter data in my jade form i get error message that says it is null. Can someone help me figuring out what the problem is?
app.js
var express = require('express');
var pg = require('pg');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var app = express();
var conString = "postgres://abc:123#localhost/abc";
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
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('/', function (req, res) {
res.render('index',
{ title : 'Home' }
)
});
app.get('/users', user.list);
app.post('/', function(req, res){
var header = req.param('header', null); // second parameter is default
var body = req.param('body', null);
console.log(header);
console.log(body);
pg.connect(conString, function(err, client, done, request, response) {
client.on('drain', client.end.bind(client));//stänger av när alla queries är klara
client.query("INSERT INTO post(member_id, title, body) VALUES ('1', $1, $2)", [header, body], function(err, result){
if (err) {
console.log(err);
}
else{
res.send("success!");
}
});
});
});
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
index.jade
extends layout
block content
h1= title
p Welcome to #{title}
form(action='/',method='post')
input(type='text',id='header',placeholder='header')
input(type='text',id='body',placeholder='body')
input(type='submit',name='submit',value='Submit')
layout.jade
doctype html
html
head
title= title
link(rel='stylesheet',href='/stylesheets/style.css')
body
block content
p whaddup
However if I use curl --verbose -d 'header=abcd&body=1234' http://localhost:3000 it works fine, so im fairly certain it's the jade part, but i've no clue what's wrong. I am new to nodejs and all that :)
thanks in advance.
It's the name of a form control that is submitted with the data, not the id. As it is, the only value your form is submitting is that of the submit button.
Rather it should look like this:
input(type='text', name='header', placeholder='header')
input(type='text', name='body', placeholder='body')

How to use session in ExpressJS?

As i understood i can use sessions only inside the requests, something like:
app.get('/', function (req, res) {
if (req.session.log_in)
res.render('index.html', config);
else
res.render('authorization.html', config);
});
But if i have for example 20 or more routes so i need to write authorization check in each route? Is there something global with sessions like in php that i could check sessions before all routes and determinate and decide on follow-up actions?
Express allows a middle parameter of middleware called for that route. Use an authorization system like Passport and call it like this:
app.get('/account', ensureAuthenticated, function(req, res){
res.render('account', { user: req.user });
});
We can manage session in ExpressJS using express-session package. If you are running it in shared resource, you need to use Redis or something to keep it consistent.
Server.js
var express = require('express');
var session = require('express-session');
var bodyParser = require('body-parser');
var app = express();
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
app.use(session({secret: 'ssshhhhh'}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
var sess;
app.get('/',function(req,res){
sess=req.session;
//Session set when user Request our app via URL
if(sess.email)
{
/*
* This line check Session existence.
* If it existed will do some action.
*/
res.redirect('/admin');
}
else{
res.render('index.html');
}
});
app.post('/login',function(req,res){
sess=req.session;
//In this we are assigning email to sess.email variable.
//email comes from HTML page.
sess.email=req.body.email;
res.end('done');
});
app.get('/admin',function(req,res){
sess=req.session;
if(sess.email)
{
res.write('
<h1>Hello '+sess.email+'</h1>
');
res.end('Logout');
}
else
{
res.write('
<h1>Please login first.</h1>
');
res.end('Login');
}
});
app.get('/logout',function(req,res){
req.session.destroy(function(err){
if(err){
console.log(err);
}
else
{
res.redirect('/');
}
});
});
app.listen(3000,function(){
console.log("App Started on PORT 3000");
});
Read complete tutorial here : http://codeforgeek.com/2014/09/manage-session-using-node-js-express-4/

Redirect loop with node express.js

I have simple webpage with /about, /contact, /home and /lessons routes defined. All routes work okay except for /lessons. I instantly get a redirect loop (Error 310 (net::ERR_TOO_MANY_REDIRECTS): There were too many redirects).
Here's my main server.js code :
var port = process.env.PORT || 8888;
var app = require('./app').init(port);
var markdown = require('./markdown');
var lessons = require('./lessons.json').lessons;
// app.use(function(req,res,next) {
// console.log('adding lessons to locals');
// res.locals.date = new Date().toLocaleDateString();
// res.locals.lessons = lessons;
// next();
// });
// app.use(app.router);
app.get('/', function (req, res) {
console.log('controller is : home');
res.locals.controller = 'home';
res.render('home');
});
app.get('/:controller', function (req, res, next) {
var controller = req.params.controller;
console.log('controller is : '+ controller);
if (controller == 'about' || controller == 'contact') {
res.locals.controller = controller;
res.render(controller);
} else {
console.log('next was taken!');
next();
}
});
app.get('/lessons', function(req, res) {
res.locals.lessons = lessons;
console.log('controller is : lessons');
res.render('lessons');
});
app.get('/lessons/:lesson', function(req, res) {
console.log('controller is : lesson');
res.locals.controller = 'lessons';
res.send('gimmie the lesson');
});
/* The 404 Route (ALWAYS Keep this as the last route) */
app.get('/*', function (req, res) {
console.log('got 404 request to ' + req.url);
res.render('404');
});
and here's the app.jsfile which is used for server initialization:
var express = require('express');
var slashes = require('connect-slashes');
exports.init = function (port) {
var app = express();
app.use(express.static(__dirname + '/public'));
// add middleware to remove trailing slash in urls
app.use(slashes(false));
app.set('views', __dirname + '/views')
app.set('view engine', 'ejs');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.logger());
app.enable("jsonp callback");
if ('development' == app.get('env')) {
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
app.use(express.logger({
format: ':method :url'
}));
}
if ('production' == app.get('env')) {
app.use(express.errorHandler());
}
app.use(function (err, req, res, next) {
console.log('Oops, something went wrong');
res.render('500.ejs', {
locals: {
error: err
},
status: 500
});
});
app.listen(port);
console.log("Listening on port %d in %s mode", port, app.settings.env);
return app;
}
I have tried debugging the app with node-inspector but it's useless since the app doesn't seem to go into any of the app.gets to try to match. It immidiately gives me the error when I try to access localhost:8888/lessons
EDIT:
I think I have found the root of the problem :
My /public dir has a lessons folder
My /views dir has a lessons.ejs view
When I change /public/lessons into /public/lessons11 for example, the problem is resolved. Can someone explain to me what's express flow in the original scenario that causes the redirect loop ? also, what can I do to resolve it ?
Thanks
This happens:
a request for /lessons comes in;
the static middleware sees the public/lessons folder and assumes that's what the intended target is; because it's a folder, it will generate a redirect to /lessons/ (see below);
static middleware picks that request up again, but notices there's no index.html in that folder, and hands it off to the next middleware (connect-slashes);
the connect-slashes middleware removes the trailing slash and issues a redirect to /lessons;
the whole loop starts again;
You can prevent the static middleware from adding a trailing slash, which will fix your redirect loop I think:
app.use(express.static(__dirname + '/public', { redirect : false }));
You can try using express-redirect-loop middleware. It uses sessions and you can read more about it and implement it at https://github.com/niftylettuce/express-redirect-loop.

Cannot POST form node.js - express

Using express 3.1.0 I have a super simple form:
<form action="/signup" method="post">
<div>
<label>Username:</label>
<input type="text" name="username"/><br/>
</div>
<div>
<label>Password:</label>
<input type="password" name="password"/>
</div>
<div><input type="submit" value="Sign Up"/></div>
</form>
and in the app.js:
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, fs = require('fs')
, User = require('./models/User.js')
, user = require('./routes/user')
, http = require('http')
, path = require('path');
var app = express();
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.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
app.get('/', routes.index);
app.get('/form', function(req, res) {
fs.readFile('./form.html', function(error, content) {
if (error) {
res.writeHead(500);
res.end();
}
else {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(content, 'utf-8');
}
});
});
app.post('/signup', function(req, res) {
var username = req.body.username;
var password = req.body.password;
User.addUser(username, password, function(err, user) {
if (err) throw err;
res.redirect('/form');
});
});
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
when trying to post this form i'm getting:
Cannot POST /signup
and in the console:
"NetworkError: 404 Not Found - http://localhost:3000/signup"
what am i missing here?
Your example works for me. I removed the references to User, user, and routes so that I can run it and the HTTP POST is received and displayed correctly in the console.
app.post('/signup', function(req, res) {
var username = req.body.username;
var password = req.body.password;
console.log("post received: %s %s", username, password);
});
I suspect the error is in your User.addUser() code.
router.route('/signup')
// (accessed at POST http://localhost:3000/api/signup)
.post(function(req, res) {
var username = req.body.username;
var password = req.body.password;
res.json(
{
message: 'signup success',
username : username,
password : password,
}
);
})
.get(function(req,res){
res.json({message: 'get request from signup'});
});
// REGISTER OUR ROUTES -------------------------------
// all of our routes will be prefixed with /api
app.use('/api', router);
You can write something like this:
action="http://localhost:3000/sin"

Couldn't get everyauth's req.user inside router functions

I am a newbie of node.js and everyauth. While I just playing around everyauth I have realized that everyauth.user works in jade views but I couldnt get req.user work inside page callbacks.
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, everyauth = require('everyauth')
, Promise = everyauth.Promise
, util = require('util')
, models = require('./models');
//Everyauth setup
everyauth.twitter
.consumerKey('XXX')
.consumerSecret('XXX')
.findOrCreateUser(function(session, accessToken, accessTokenSecret, twitterData){
var promise = new Promise();
models.findOrCreateTwitterUser(twitterData,promise);
return promise;
})
.redirectPath('/');
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.static(__dirname + '/public'));
app.use(express.cookieParser());
app.use(express.session({secret:"Iam james bond"}));
app.use(express.methodOverride());
//app.use(app.router);
app.use(everyauth.middleware());
});
app.configure('development', function(){
everyauth.debug = true;
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.get('/', function(req, res){
if(req.loggedIn){
console.log(req.user); //<--This is always undefined
}
console.log("index");
res.render('index', { title: 'Welcome to Chat app' });
});
//Helpers
everyauth.helpExpress(app);
app.listen(3000);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
Here is the problematic part
app.get('/', function(req, res){
if(req.loggedIn){
console.log(req.user); //<--This is always undefined
}
console.log("index");
res.render('index', { title: 'Welcome to Chat app' });
});
It seems I am missing some point. The weird part is req.loggedIn works as expected but somehow everyauth don't populate user data.
To access the 'user' by req.user you need to configure everyauth.everymodule.findUserById like below
//Everyauth setup
....
....
everyauth.everymodule.findUserById( function (userId, callback) {
var db = app.set('db');
var User = db.main.model('User');
User.findById(userId, callback);
// callback has the signature, function (err, user) {...}
});
....
....
var app = module.exports = express.createServer();
//Configuration
I've been having issues with everyauth req.user with the latest versions. What I do is I use "req.session...". So If I want to get the user while under the facebook oauth, I'd use req.session.auth.facebook.user.id, and this gives me the users Id.
console.log(req.session) and from there extract whatever information you want to use.

Resources