How is the express req.session object persisted?

24,227

Solution 1

There's an overall session data structure that stores all session info for all users (like a global, but it could also be in a database - just something that is persistent at least across connections). Each client's session data uses one unique key to index into the session store to get the session data for that client.

Part of establishing a session for a given browser client is creating a unique client key (which will usually be stored in a cookie) that becomes the index into the global session object.

On an incoming http request, Express middleware that supports the session checks a particular client cookie and if that particular cookie is found on the http request and is found in the global session object/database, then it adds that session's stored info to the request object for the http request handler to later use.

So, here's a typical sequence:

  1. Incoming HTTP request.
  2. Middleware checks for session cookie.
  3. If session cookie not there, then create one and, in the process created a unique id to identify this http client.
  4. In the persistent session store, initialize the session for this new client.
  5. If session cookie is there, then look in the session store for the session data for this client and add that data to the request object.
  6. End of session middleware processing
  7. Later on in the Express processing of this http request, it gets to a matching request handler. The session data from the session store for this particular http client is already attached to the request object and available for the request handler to use.

Solution 2

I think the accepted answer misses one crucial detail, which was surfaced by @jpaddison3: "Express-session hooks res.end() to see when the request is done and then it updates the session store if needed."

Basically, when you add the expression-session middleware, it wraps res.end() so that the new session information is saved just before the stream is closed.

Share:
24,227

Related videos on Youtube

NicholasFolk
Author by

NicholasFolk

Updated on September 26, 2021

Comments

  • NicholasFolk
    NicholasFolk over 2 years

    I'm very new to learning Node and Express, and I'm still trying to wrap my head around the code flow with express. Suppose we have code that looks like this in a session.js:

    app.post('/session', notLoggedIn, function(req, res) {
        User.findOne({
            username: req.body.username, 
            password: req.body.password
        }, function (err, user) {
            if (err) {
                return next(err);
            }
            if (user) {
                req.session.user = user;
                res.redirect('/users');
            } else {
                res.redirect('/session/new');
            }
        }); 
    });
    

    Assuming the User is a required mongo schema. What I find strange is the session.user assignment:

    req.session.user = user;
    

    Since the req variable will be out of scope after the redirect, but we're obviously doing this to persist the user data, I'm left with figuring out which of the following scenarios describe what is happening. Either (A) the argument that's being assigned to the req parameter (when the callback is called) is stored/somewhere still on the stack, (B) the session is stored/on the stack and being assigned to a new req object before it's passed in to the callback, or (C) the same as B, but on the user field (seems unlikely and maybe contrived on my part).

  • Suraj Jain
    Suraj Jain over 6 years
    Can we chat, i have few doubts, and a little help will be a huge benefit for me.
  • jfriend00
    jfriend00 over 6 years
    @SurajJain - That's not how this site works. If you have a question about how this works, you can post a new question yourself with the specific details about what you need help in understanding.
  • Suraj Jain
    Suraj Jain over 6 years
    I use to do that earlier, people only down-vote, that is why I ask in chat now, and chat and completely understand, and then answer questions on this site, and spread the knowledge.
  • jpaddison3
    jpaddison3 almost 3 years
    So if I tell express to use connect-mongo, it would store the global session object there? Am I then to assume that all assignments to the session object lead to a database write? Presumably asynchronously?
  • jfriend00
    jfriend00 almost 3 years
    @jpaddison3 - Yes, that is generally the idea.
  • jpaddison3
    jpaddison3 almost 3 years
    Thanks @jfriend00. One thing that occurred to me is that the session would be written to the DB all at once at the end of serving the request. I was previously thinking it would lead to (to my mind) awkward writes being fired in the background after each assignment to the object.
  • jfriend00
    jfriend00 almost 3 years
    @jpaddison3 - You can either call req.session.save() yourself when you want to update the session store with the current data or express-session will do that for you when the request is done and it notices that anything changed in the session. Express-session hooks res.end() to see when the request is done and then it updates the session store if needed.