0

This example is taken from Node Cookbook, but using Express 3.1.0:

app.js

var express = require('express')
  , routes = require('./routes')
  , 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(express.cookieParser('kooBkooCedoN'));
  app.use(express.session());
  app.use(require('./login'));

  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

// --------------------------
// MODIFICATION IS MADE HERE!
// --------------------------
app.configure(function(){
  app.use(function(req, res, next){
    res.locals.user = req.session.user;
    next();
  });
});

app.get('/', routes.index);
app.post('/', routes.index);
app.del('/', routes.index);
app.get('/:page', routes.index);

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

I have made some modification to the code as suggested in: Migrating Express.js 2 to 3, specifically app.dynamicHelpers() to app.locals.use?

login.js

var users = {'dave' : 'expressrocks'};

module.exports = function (req, res, next) { var method = req.method.toLowerCase(), //cache the method
    user = req.body.user,
    logout = (method === 'delete'),
    login = (method === 'post' && user),
    routes = req.app.routes.routes[method];

  if (!routes) { next(); return; }

  if (login || logout) {
    routes.forEach(function (route) {
      if (!(req.url.match(route.regexp))) {
        console.log(req.url);
        req.method = 'GET';
      }
    }); 
  }
  if (logout) {
    delete req.session.user; 
  }
  if (login) {
    Object.keys(users).forEach(function (name) {
      if (user.name === name && user.pwd === users[name]) {
        req.session.user = {
          name: user.name,
          pwd: user.pwd
        };
      }
    }); 
  }
  if (!req.session.user) { req.url = '/'; } 
  next(); 
};

login.jade

if user
  form(method='post')
    input(name="_method", type="hidden", value="DELETE")
    p Hello #{user.name}!
      a(href='javascript:', onClick='forms[0].submit()') [logout]
else
  p Please log in
  form(method='post')
    fieldset
      legend Login
      p
        label(for="user[name]") Username:
        input(name="user[name]")
      p
        label(for="user[pwd]") Password:
        input(type="password", name="user[pwd]")

      input(type="submit")

Result Log from terminal

The error is came from the line: routes = req.app.routes.routes[method]; in login.js

TypeError: Cannot read property 'get' of undefined
    at Object.module.exports [as handle] (/home/chiasyan/Desktop/login/login.js:8:35)
    at next (/home/chiasyan/Desktop/login/node_modules/express/node_modules/connect/lib/proto.js:199:15)
    at store.get.next (/home/chiasyan/Desktop/login/node_modules/express/node_modules/connect/lib/middleware/session.js:309:9)
    at /home/chiasyan/Desktop/login/node_modules/express/node_modules/connect/lib/middleware/session.js:333:9
    at /home/chiasyan/Desktop/login/node_modules/express/node_modules/connect/lib/middleware/session/memory.js:50:9
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)

Update: I have changed the routes = req.app.routes.routes[method]; but there is still a minor error.

The user variable could not be found in login.jade (user is defined once in the login.js)

ReferenceError: /home/chiasyan/Desktop/login/views/login.jade:1
  > 1| if user
    2|   form(method='post')
    3|     input(name="_method", type="hidden", value="DELETE")
    4|     p Hello #{user.name}!

user is not defined

Quote from Node Cookbook

In routes/index.js, we can now simply have the following code:

index.js

exports.index = function (req, res) { 
  res.render('index', {title: 'Express'}); 
};

Another quote from Node Cookbook

Since we're no longer using routes, we don't have the opportunity to pass req.session. user through res.render. However, we can use a dynamic helper instead. Dynamic helpers have access to the req and res objects, they're called just before a view is rendered. Any properties we pass to the dynamic helper object are pushed to the Jade view as local variables.

Since I can no longer use dynamic helpers in Express 3.*, so in app.js I have changed to:

app.configure(function(){
  app.use(function(req, res, next){
    res.locals.user = req.session.user;
    next();
  });
});
Community
  • 1
  • 1
chiasyan
  • 11
  • 1
  • 1
  • 3

2 Answers2

1

There is an error in the line that you mentioned:

routes = req.app.routes.routes[method];

You should use

routes = req.app.routes[method];

As an aside, what is the purpose of the check that you do with the result of this code?

Update: In order to pass the user information to your Jade view you need to pass this information in the render call. For example:

# Assuming you've got the user information in req.session.user 
console.log(req.session.user);
res.render('login', {user: req.session.user});
Hector Correa
  • 26,290
  • 8
  • 57
  • 73
  • Hi Hector, thank you for your answer. I have changed to the solution that you have provided but there is still an error. Please refer back to my original post under update section. As for the result, it is the log from the terminal which I hope giving more information of the problem. Please advise. – chiasyan Feb 05 '13 at 00:49
  • Could you also include the code where you call res.render() ? You should be *passing* user as a parameter when you call render. – Hector Correa Feb 05 '13 at 00:58
  • Hi Hector, please refer to the update section again. The _res.render()_ is called once in _index.js_. Sorry, this is my very first web code. – chiasyan Feb 05 '13 at 01:35
  • I've updated the answer with what you need to do to pass the user information to the view. – Hector Correa Feb 05 '13 at 01:59
  • Hector, I have included another quote from the book in the update section indicating that we don't have the opportunity to pass _req.session.user_ through _res.render_. The moment you provide the solution, I have the code working (please refer to my new answer) but not sure if it the the right way. Please advise. Thank you very much for your assistance, I am much clearer now on how everything is connected. – chiasyan Feb 05 '13 at 02:18
1

I have the code running now but I am not sure if it is the correct way. Please advise if anything rectification should be made.

I modified

app.configure(function(){
  app.use(function(req, res, next){
    res.locals.user = req.session.user;
    next();
  });
});

into

app.use(function(req, res, next){
  res.locals.user = req.session.user;
    next();
});

and placed it right after the following line

app.use(require('./login'));

Besides the answer given by Hector Correa in this post, here is the complete working code after the correction.

app.js

var express = require('express')
  , routes = require('./routes')
  , 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(express.cookieParser('kooBkooCedoN'));
  app.use(express.session());
  app.use(require('./login'));

  app.use(function(req, res, next){
    res.locals.user = req.session.user;
    next();
  });

  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.post('/', routes.index);
app.del('/', routes.index);
app.get('/:page', routes.index);

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

login.js

var users = {'dave' : 'expressrocks'};

module.exports = function (req, res, next) { var method = req.method.toLowerCase(), //cache the method
    user = req.body.user,
    logout = (method === 'delete'),
    login = (method === 'post' && user),
    routes = req.app.routes[method];

  if (!routes) { next(); return; }

  if (login || logout) {
    routes.forEach(function (route) {
      if (!(req.url.match(route.regexp))) {
        console.log(req.url);
        req.method = 'GET';
      }
    }); 
  }
  if (logout) {
    delete req.session.user; 
  }
  if (login) {
    Object.keys(users).forEach(function (name) {
      if (user.name === name && user.pwd === users[name]) {
        req.session.user = {
          name: user.name,
          pwd: user.pwd
        };
      }
    }); 
  }
  if (!req.session.user) { req.url = '/'; } 
  next(); 
};
chiasyan
  • 11
  • 1
  • 1
  • 3