Skip to content

Missing Session Data #167

@brimsey

Description

@brimsey

It is possible for back-to-back requests to be missing session data.

Say you have a webapp with 2 routes. Route /a stores a value in the session and then redirects to route /b. Route /b simply prints the value stored in the session. If the session store is slow, it is possible to hit route /b before the session is persisted. express-session starts writing a response back to the browser in writetop() before the session is persisted. once the session data is persisted, express-session calls writeend(). When express-session executes writetop(), the browser gets the 302 redirect and performs the get on route /b before the session data is persisted. When route /b prints its session data, the stored value is not there. I believe express-session should not perform writetop() and only call writeend() once the session data is persisted.

Webapp:

/a
req.session.key = 'value';
res.redirect("/b")

/b
console.log(req.session.key)

A sample log file would like this:

GET /a

  • start writing session (session store log)
  • redirect to /b

GET /b

  • get session (session store log)
  • done writing session (session store log)
  • print session data (req.session.key missing)

Most of the time the session data is persisted before the request for /b and everything proceeds as expected, but once in a while the request for /b will arrive before the session data is persisted causing problems.

To get around this problem, I removed the writetop() from index.js and fixed up the if logic:

  // touch session
  req.session.touch();

  if (shouldSave(req)) {
    req.session.save(function onsave(err) {
      if (err) {
        defer(next, err);
      }

      return writeend();
    });
  } else if (storeImplementsTouch && shouldTouch(req)) {
    // store implements touch method
    debug('touching');
    store.touch(req.sessionID, req.session, function ontouch(err) {
      if (err) {
        defer(next, err);
      }

      debug('touched');
      writeend();
    });

    return writetop();
  } else {
    return _end.call(res, chunk, encoding);
  }

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions