agnsaft
agnsaft

Reputation: 1891

How to force Tornado websockets to generate error page on handshake

I am writing a small app where I use Tornado websockets. I use cookies for authentication, and I therefore want to check this when establishing the web socket.

So here is the challenge (building on the official websockets example):

class EchoWebSocket(tornado.websocket.WebSocketHandler):
    def open(self):
        userx = self.get_secure_cookie("user")
        if not userx:
            self.send_error(403) #I want to redirect or otherwise stop the user
        print "WebSocket opened"

    def on_message(self, message):
        userx = self.get_secure_cookie("user")
        self.write_message(u"%s said: %s" % (userx, message))

    def on_close(self):
        print "WebSocket closed"

Turns out that this is not very popular with Tornado, throwing this error:

ERROR:root:Exception in callback <tornado.stack_context._StackContextWrapper object at    0x10fa10db8>
Traceback (most recent call last):
 ....
  File "/Library/Python/2.7/site-packages/tornado-2.4-py2.7.egg/tornado/iostream.py", line 565, in _check_closed
raise IOError("Stream is closed")
IOError: Stream is closed

Is it even possible to "authenticate or cancel" during websockets handshake? Is this a problem with my code, or is there a issue/missing feature with Tornado? Is Tornado capable of sending some error condition over websockets to trigger the onerror handler at the client side in this situation (can not find any way to force an error condition in the manual)?

The sequence of events I am trying to achieve is:

  1. the user logs in using regular web requests, and a session token is stored as a secure cookie

  2. the user loads a page that uses websockets, javascript attempts to establish the socket

  3. before the socket is established I want to check the presence of a valid session token

    • if valid token, the socket is established and my app works as intended
    • if invalid token, there is no socket, and the user gets an error (alternatively, an websocket error condition is raised by the server)

Upvotes: 1

Views: 1769

Answers (3)

securecurve
securecurve

Reputation: 5817

You can track your users, you can do it easily, as each user connects to the server is created an instance, check this SO link.

Regarding that you want to close the connection if he is not authenticated, you a can do it by calling close() method inside WebSWebSocketHandler instance like this:

class WSHandler(tornado.websocket.WebSocketHandler):

def open(self):
    if not condition:
        self.close()

Check this in Tornado: tornado.websocket.WebSocketHandler.WebSocketHandler.close()

I didn't try it by myself. You can try it and tell me if it works for you.

Upvotes: 3

agnsaft
agnsaft

Reputation: 1891

It looks like the answer to this question is as Nikolay Fominyh suggests (although I can not accept that answer since its a comment and not an answer) to send message to user and close connection. This currently seems to be the best way to solve this.

Upvotes: 0

uwu
uwu

Reputation: 1738

Is this?

http://www.tornadoweb.org/documentation/web.html#tornado.web.RequestHandler.write_error

You can overwrite handle.write_error method, But I do not know whether WebSocketHandler includes this method

Upvotes: 1

Related Questions