Accessing Session in Websocket
darrudi opened this issue · 8 comments
Hi Peter,
Is it possible to access the session in websocket connections?
Currently I set a session variable username
for each user after login. The client also connects to total.js using websocket to get updates & notifications. I need to get the username
in websocket connections to route the notifications.
I access the session in normal total.js contollers via this.session; However It seems this.session
is null inside the websocket controller.
My code in controllers/default.js
:
exports.install = function(framework) {
framework.route('/*', view_app);
// other routes
framework.websocket('/', socket_homepage, ['json']);
};
function view_app() {
var self = this;
// self.session is OK here
}
function socket_homepage() {
var self = this;
// self.session is undefine!
}
Question: does websocket requests share the same session cookies with normal http requests? If yes,
is there any way to resolve the session variables based on the cookie sent by the browser?
Thanks in advance,
in the meantime I came up with an implementation to do it:
in the websocket controller:
exports.install = function(framework) {
framework.websocket('/', socket_homepage, ['json']);
};
function socket_homepage() {
var controller = this;
controller.on('open', function(client) {
client.session = loadSessionByCookie(client);
// logic ...
}
}
function loadSessionByCookie(client) {
if (!client || !client.req || !client.req.headers)
return;
var cookie = client.req.headers.cookie;
if (!cookie)
return;
var id = client.cookie(framework.config.cookie_prefix) || '';
if (id.length === 0) {
return;
}
var obj = framework.decrypt(id, framework.config.cookie_secret);
if (obj === null) {
return;
}
if ('ssid_' + obj.sign !== cookieSignature(obj.id, client)) {
return;
}
var session = framework.cache.read(obj.id);
return session;
}
function cookieSignature(id, client) {
return id + '|' + client.socket._peername.address.replace(/\./g, '') + '|' + client.req.headers['user-agent'].substring(0, USERAGENT).replace(/\s|\./g, '');
}
cookie_prefix
and cookie_secret
must be set in the config
file and match exactly the values used by session.js
.
the above code is a mimic of what happens in the session.js
module. I am sure there are better ways to implement it; maybe by intercepting websocket requests and reusing session.js
middleware (what happens to HTTP requests by default).
Hi @darrudi,
sorry for my delay, I have been sick. What version of total.js do you use? I'll test the problem during the weekend and I'll give you a feedback.
Thanks and sorry.
I am using version 1.6.0-1 (package.json)
For the moment I found a workaround as explained above. However it would be a good idea for the framework to provide the session in websocket connections by default.
Hope you get well as soon as possible.
@darrudi Please download latest version from GitHub, it's really good.
I'll fix it. Thanks.
Hi @darrudi, I fixed it. I found a problem in the framework and in the module. You must use total.js from GitHub (v1.7.0).
I updated total.js to version 1700. Now the session is accessible for websocket requests. However the session modules raises the following error:
it is the relevant code in the session module:
framework.middleware('session', function(req, res, next) {
if (res.statusCode) {
// classic HTTP
res.once('finish', function() {
session._write(req._sessionId, req.session);
});
} else {
// websocket
res.socket.on('close', function() {
session._write(req._sessionId, req.session);
});
}
session._read(req, res, next);
});
it seems res
is null for websocket connections. I can nest the if ... else ...
block inside another if (res) { ... }
however the session data is not refreshed after each response this way.
Hi @darrudi,
I found a problem in the framework middleware.call(framework, req, null, next);
. Can you test it? Please download latest version from GitHub. Thanks!
I works perfectly Peter 👍
Thanks
By the way there was an error in Session.prototype._signature
that seems to be resolved in the update (req.headers
was null for websocket connections and threw and error when calculating the signature). Anyway it's ok now.