Jason Holm
Jason Holm

Reputation: 33

How can I use Node.js Express-session inside a conditional middleware?

var express = require('express')
var parseurl = require('parseurl')
var session = require('express-session')

var app = express()


app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true
}))

This is my simple code. However, I want to use session only if the req.url contains /web. Is there a way I can wrap this inside a middleware of my own?

I've tried:

function setSession(req,res,next){
    if(req.url.indexOf('/api') != 0){
        app.use(session({
            secret: 'keyboard cat',
            resave: false,
            saveUninitialized: true
        }));
        next();
    }else{
        next();
    }
};

and then

app.use(setSession);

But setting req.session.hello = "world" in my controller gives: TypeError: Cannot set property 'hello' of undefined. Simply put, it doesn't work. Are my arguments wrong in my middleware?

Upvotes: 1

Views: 995

Answers (1)

Andrew Lavers
Andrew Lavers

Reputation: 8151

However, I want to use session only if the req.url contains /web. Is there a way I can wrap this inside a middleware of my own?

You certainly can. You can use express.Router to create sub-routes, like this:

var sessionMiddleware = session({
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: true
});

var webRoutes = express.Router()
    .get('/', function(req, res, next) {
        res.send('I have a session!');
    });

var nonWebRoutes = express.Router()
    .get('/', function(req, res, next) {
        res.send('No session here');
    });


app.use('/web', express.Router()
    .use(sessionMiddleware)
    .use(webRoutes));

app.use('/nonweb', nonWebRoutes);

Edit:

If however you want to conditionally execute the middleware function, you could do it like this:

app.use(function(req, res, next) {
    if (req.url.indexOf('/api') !== 0) {
        sessionMiddleware(req, res, next);
    } else {
        next();
    }
});

app.get('/api', function(req, res, next) {
    res.send(!!req.session); //false
});

app.get('/web', function(req, res, next) {
    res.send(!!req.session); //true
});

But I prefer the sub-route approach because it maps your path route structure to a hierarchy which makes the code easier to read and easier to incorporate other middleware that make use of sessions, like passport.js for example.

Upvotes: 2

Related Questions