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 ?
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:
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.
Then pass the new session ID as a cookie
parameter while reconnecting the socket:
socket.socket.connect('/?cookie=<newSessionID>')
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With