Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to get session for socket in sailsjs after restart

I trying to build socket driven application on sailsjs, it is small and I need only memory session adapter, but when I restart application, I getting after socket.get('/'):

Could not parse: No session data returned, and an error was encountered saving session data for the first time: undefined SyntaxError {stack: (...), message: "Unexpected token N"} sails.io.js:142

Uncaught Error: Server response could not be parsed!
No session data returned, and an error was encountered saving session data for the first time: undefined 

I understand that my session is lost, but can't find any way to restore it, or even take care of this error.

Is there any way to request new session cookie for socket without reloading the page ?

like image 493
zb' Avatar asked Jan 14 '14 05:01

zb'


2 Answers

The problem here is that by default Sails uses MemoryStore to handle sessions, which means whenever you lower Sails (or whenever the application crashes, even if it is being restarted with forever, etc.) all the sessions will just be automatically gone.

The solution is as simple as changing the session handling to an external adapter. In config/session.js generated by default you already have two examples of setup for such an adapter, namely, for Redis and MongoDB, so all you have to do is to uncomment corresponding lines (and don't forget a comma after secret value). For example, if you go with mongo, it'll be something like

module.exports.session = {
  secret: 'c827f7e0dc520d83d63b5c9c055b1d00', // !!

  // Redis setup example is here...    

  // Uncomment the following lines to use your Mongo adapter as a session store
  adapter: 'mongo',
  host: 'localhost',
  port: 27017,
  db: 'sails',
  collection: 'sessions'

  // Optional Values:
  //
  // # Note: url will override other connection settings
  // url: 'mongodb://user:pass@host:port/database/collection',
  //
  // username: '',
  // password: '',
  // auto_reconnect: false,
  // ssl: false,
  // stringify: true    
};

Of course, in this case you should have mongod running on your machine.

UPDATE

Ok, if there is a MemoryStore limitation which can't be avoided (that was the original question), then reinitializing the socket session without reloading the page becomes a bit tricky, but still possible. In order to do it one should:

  1. Make an AJAX (or JSONP in case of CORS) request to your server to get the new session ID. For example, it can be as simple as having a controller returning a JSON with the session ID, let's say api/controllers/TestController.js:

    module.exports = { index: function(req, res) { res.send(req.sessionID); } };

So, once you detected that the session is lost, use $.get('/test') to get the new session ID.

  1. Then pass the new session ID as a cookie parameter while reconnecting the socket:

    socket.socket.connect('/?cookie=<newSessionID>')

  2. socket.get("/", function (response) { console.log(response); }) will work after that.

It's kind of a quick hack, and there's probably a more elegant way to wrap it (e.g. send session ID in headers, not in the body, etc.), but the idea is simple: make an AJAX-request to get a new session and pass its ID as cookie parameter to reconnect the socket.

like image 154
bredikhin Avatar answered Oct 12 '22 01:10

bredikhin


I had the same problem, and reading this issue i realised that a new session will be created just after an http request to sails. I have the front end served separately on static files, thus i use just socket.io towards sails, and this is the reason why the session is not renewed.

With either a persistent or volatile session adapter, when a session is expired it should be renewed.

So, without the need to switch to a persistent adapter, i just added an empty file under the sails assets folder, like in assets/js/renew-session.js (empty file), and included it as a script in the index of my app. This way, the initial HTTP request renews the cookies.

Maybe this can be useful to somebody else

like image 45
danza Avatar answered Oct 12 '22 00:10

danza