Search code examples
expresspassport.jsexpress-session

Error accessing req.session.variable method


I added a custom object when I visit a route to my req.session if I have a loggen in user, I am using passport and express.

router.get('/', function(req,res) {
  if((!req.session.myObject) && (req.isAuthenticated())) {
    req.session.myOBject = new myObject();
  }
});

But then in another route if I do

req.session.myObject.myMethod() 

I get an error that myObject.myMethod is not a function, whereas if in that route I run

var myObject = new Object();
myObject.myMethod();

it works, but obviously I dont want to create a new Object there, I want to have 1 myObject that is created on the first time I view the root page and am loggedIn.

Why do I get this error???? How do I get around it???

Thanks


Solution

  • Session stores for express-session typically store the session data as JSON in between requests.

    A custom class/object won't be serialized and deserialized to/from JSON directly, which means that you have to check if the session store that you're using provides functionality to "hook" the (de)serialization.

    For instance, connect-mongo has serialize/unserialize options that you can use for this purpose, the idea being that you "convert" your class instances to something that is JSON-serializable, and during unserialization convert that "something" back to an instance of your class.

    Alternatively, you can define a toJSON method in your class to serialize the instances, and use a regular Express middleware to convert this data back to an instance.

    The consequence of all this though is that new instances of your class get created for each request. I don't see how you can get around that.

    EDIT: here's an (untested) example for connect-mongo. I'm using serialise to easily create JSON-stringifiable versions of your class. This may or may not work for your particular situation, so YMMV.

    // Load `serialise` and register your class with it.
    const S = require('serialise');
    S.serialisable(myObject);
    
    // Create the `connect-mongo` session store instance
    let store = new MongoStore({
      ...,
      serialize : session => {
        session.myObject = S.serialise(session.myObject);
        return session;
      },
      unserialize: session => {
        session.myObject = S.deserialise(session.myObject);
        return session;
      }
    });
    

    Again, the code above is untested and may fail (I'm not intimately familiar with connect-mongo), but hopefully it'll give you an idea on how this could be implemented.