8

I'm trying to build a chat application based on sails.js. The url for messages from a specific chat looks like this:

/api/chat/:id/messages

When I request this url with XHR, it provides a session cookie and sails.js builds a session object. I can easily check user rights to read the messages from the specific chat.

However, I need to request this url with socket.io so that the client can subscribe to all future changes of the messages collection.

When I request this url with socket.io, no session cookie is set and the sails.js session is empty. So, I cannot check the user rights on the server-side.

I do understand that socket requests are not HTTP-requests. They don't provide any cookies on their own.

Is there any simple workaround?

dbasch
  • 1,698
  • 1
  • 15
  • 31
alevkon
  • 327
  • 4
  • 13
  • To clarify- you're having this trouble cross-domain, right? As in you're embedding a script on www.foo.com and opening a socket to www.bar.com? – mikermcneil Aug 17 '13 at 19:16
  • No, Mike – it's not cross-domain issue. I've finally found the answer and posted it below. You have to access your socket session object in a different way. P.S. Maybe you should implement this workaround into sails.js core. – alevkon Aug 18 '13 at 08:26

4 Answers4

5

I found a way to get the session object which was set while socket.io handshaking. In your controller, you should do something like this:

myControllerAction: function(req, res) {
    var session = req.session;
    if (req.isSocket) {
        var handshake = req.socket.manager.handshaken[req.socket.id];
        if (handshake) {
            session = handshake.session;
        }
    }
    //session now contains proper session object
}

You can implement this in sails.js policy, and attach this policy to some controllers. But don't write you socket session into req.session! Otherwise, you'll get an error trying to respond to the client (original req.session is still used in some way). Instead, save it as req.socketSession or something like that.

alevkon
  • 327
  • 4
  • 13
3

please send a JSONP request from your application before sending a socket request,that will create a cookie and accepts socket requests.

Shiva Gouraram
  • 147
  • 1
  • 7
  • How this should help? I already have a cookie before initializing socket.io handshake. What address should I request with JSONP? Why JSONP, not simple Ajax? – alevkon Aug 16 '13 at 14:45
  • could you paste your error here?is your client and server are in same domain ,please provide additional details. – Shiva Gouraram Aug 16 '13 at 15:47
  • 1
    This answer is what the rest of the team and I have done in the past-- to clarify, it sounds like you're doing sockets cross-domain, yeah? The trouble is that the browser doesn't send cookies when it establishes the websocket connection. Unfortunately, you may find that there are still problems in Safari. @alevkon You won't be able to use basic AJAX because it's cross-domain-- you'll need to use JSONP or CORS (and CORS is not fully supported < IE8) – mikermcneil Aug 17 '13 at 19:16
1

You can do your initial login over the socket.post() instead of XHR, subsequent socket requests will be authorized.

aaron
  • 86
  • 6
0

alevkon,in the above mentioned method you have to implement the same in all the controllers,because you don't know which controller is accessed for the first time...but by sending just one jsonp request you can create a cookie between client and server,the same cookie is used until the next session.

Shiva Gouraram
  • 147
  • 1
  • 7
  • 1
    Shiva, It's not cookie issue. I have some AJAX requests already sent before socket handshaking, so the sails.sid cookie is already set. The problem was not about cookies, the problem was how to access session object from controllers. if your req.isSocket is true, you won't find the proper session in your req.session object, but you still can access it in the way I described. – alevkon Aug 18 '13 at 08:34