Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fails when i use connect-mongodb to store the session #4

Open
jfromaniello opened this issue Jan 7, 2013 · 4 comments
Open

fails when i use connect-mongodb to store the session #4

jfromaniello opened this issue Jan 7, 2013 · 4 comments

Comments

@jfromaniello
Copy link

This is a so convoluted error that took me a while to discover.. It is an specific combination of modules (request and connect-mongodb).

Here is the smallest version I did:

//npm install express request mongodb connect-domain connect-mongodb

var request = require('request'),
    express = require('express'),
    connectDomain = require('connect-domain'),
    http = require('http');

var MongoStore = require('connect-mongodb'), 
    Db = require('mongodb').Db, 
    Server = require('mongodb').Server, 
    server_config = new Server('localhost', 27017, {auto_reconnect: true, native_parser: true}), 
    db = new Db('test', server_config, {}),
    mongoStore = new MongoStore({db: db});

var app = express();

app.configure(function(){
  //if i move this line after express.session 
  //everything works as expected.
  this.use(connectDomain());

  this.use(express.cookieParser());
  this.use(express.session({secret: 'foobar', store: mongoStore }));

  this.use(app.router);

  this.use(function(err, req, res, next){
    res.end(err.message);
  });
});

app.get('/', function(req, res, next){
  var r = request.get('http://localhost:9999');
  //at this point r.domain is null.

  //If i explicitly add this stream to the domain it works
  //Slightly changing connect-domain to store the domain in req, if i do 
  //req.__domain.add(r); it works
  r.pipe(res);
});

http.createServer(app).listen(3000, function(){
  console.log('listening on http://localhost:3000');
});
@rabbitfufu
Copy link

I have the exact same problem when using Redis as a session store.

@emostar
Copy link

emostar commented May 30, 2013

I had the same issue and upon further inspection it appears that adding a process.nextTick to RedisStore gets it working if you use the domain middleware first.

The MemoryStore session store for express includes the process.nextTick, but RedisStore didn't. When I add the session middleware, if I do it like this, it will work with domains:

var sessionFn = express.session({ store: new RedisStore(redisOptions),
  cookie: {httpOnly: true, maxAge: 7 * 24 * 60 * 60 * 1000},
  secret: ****"'})
 app.use(function (req, res, next) {
  process.nextTick(function() {
    sessionFn(req, res, next)
  })
})

I'm not sure why, I guess it has something to do with how domains work though.

@jpillora
Copy link

The problem is, this module calls dispose()s too early, which causes callbacks to silently cancel...

As a solution, I've wrapped dispose in process.nextTick, and I'm not using this module, as it's under 20 lines:

    var domain = require('domain');
    ...
    app.use(function(req, res, next) {
      var d = domain.create();

      function dispose() {
        //let dust settle
        process.nextTick(d.dispose.bind(d));
      }

      res.on('close', dispose);
      res.on('finish', dispose);

      d.on('error', function (err) {
        dispose();
        next(err);
      });

      d.run(next);
    });

Will create a new module soon...

@jpillora
Copy link

Beware, asynchronous jobs related to the request will get closed after a tick, so if they last longer than that, they will get silently cancelled. This is good and bad, good because it clears up callbacks related to a crash, though bad if you're wanting to do something in after the request, like logging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants