"New" redis session store with express, asynchronous creation?

Viewed 27

I the past I could just easily add session management using redis as store in express using express-session like so:

import session from "express-session";

module.exports = (config?: {[p: string]: unknown}) => {

  server.use(cookieParser());
  // etc etc
  server.use(session(sessCfg));

  server.use('/', router);
  return server;
}

This still work when creating a memory store/default store:

import session from "express-session";

import express = require('express');
const server = express();
function sessCfgGenerator() {
  return {
    "secret": "fdakjlhgafgdsahjkhldg",
    "name": "bondinet.sid",
    "cookie": {
      "httpOnly": true,
      "secure": false
    },
    "resave": false,
    "saveUninitialized": true,
    "unset": "destroy",
  }
} 

module.exports = (config?: {[p: string]: unknown}) => {

  server.use(cookieParser());
  // etc etc
  server.use(session(sessCfgGenerator()));

  server.use('/', router);
  return server;
}

However nowadays to generate a redis store you have to create the client settings and then asynchronous connect to it.

let redisClient = redis.createClient({
    socket: {
        reconnectStrategy: function (retries: number) {
            if (retries > 1000) {
                // End reconnecting with built in error
                return new Error("Retry time exhausted");
            }
            // reconnect after
            return Math.min((retries + 1) * 100, 60000);
        },
    }
});
await redisClient.connect();
store = new RedisStore({
    client: redisClient,
    prefix: prefix,
});

I've tried to include the code into the above loader. To make sure it awaits for redis to start/connect:

import session from "express-session";
import express = require('express');

const server = express();

async generateRedisStore(prefix) {
    let redisClient = redis.createClient({
        socket: {
            reconnectStrategy: function (retries: number) {
                if (retries > 1000) {
                    // End reconnecting with built in error
                    return new Error("Retry time exhausted");
                }
                // reconnect after
                return Math.min((retries + 1) * 100, 60000);
            },
        }
    });
    await redisClient.connect();
    return new RedisStore({
        client: redisClient,
        prefix: prefix,
    });
}
async function sessCfgGenerator() {
    const opt = {
        "secret": "fdakjlhgafgdsahjkhldg",
        "name": "bondinet.sid",
        "cookie": {
            "httpOnly": true,
            "secure": false
        },
        "resave": false,
        "saveUninitialized": true,
        "unset": "destroy",
        store: await generateRedisStore('');
    }
} 

module.exports = (config?: {[p: string]: unknown}) => {

    server.use(cookieParser());
    // etc etc
    sessCfgGenerator.then(cfg => {
        server.use(session(cfg));
        console.log("SESSION STARTED");
    });

    server.use('/', router);
    return server;
}

However when I use the asynchronous version I notice that the session management is actually never "available". Even though the line runs (I see clearly the "SESSION STARTED" in the logs), whenever I test a route the session isn't there (below shows "undefined"):

router.get('/test', function(req, res, next) {
  const r = 'respond with a test - ' + (req.session ? "loaded" : "undefined");
  res.send(r);
});

What is the solution, and how can I make this work? These are actively used libraries so it must be working right?

0 Answers
Related