Tornado websockets supporting binary
Question: I am using tornado as a server. I would like it to receive binary data. The
server side is as simple as simple gets:

    
    
    import tornado.websocket
    import tornado.httpserver
    import tornado.ioloop
    import tornado.web
    
    class WebSocketServer(tornado.websocket.WebSocketHandler):
        def open(self):
            print 'OPEN'
    
        def on_message(self, message):
            print 'GOT MESSAGE: {}'.format(message)
    
        def on_close(self):
            print 'CLOSE'
    
    
    app = tornado.web.Application([
            (r'/', WebSocketServer)
        ])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(9500)
    tornado.ioloop.IOLoop.instance().start()
    

This server is just used to visualize incoming data, not too special. The
server works just find with standard ascii, but it explodes when it gets any
unicode (my test for fake binary data). I used the site
<http://www.websocket.org/echo.html> and redirected the sending to go to
`ws://172.0.0.1:9500/` which is where I set up the server. The server then
prompted me with the very nasty error:

    
    
    ERROR:tornado.application:Uncaught exception in /
    Traceback (most recent call last):
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site packages/tornado/websocket.py", line 303, in wrapper
        return callback(*args, **kwargs)
      File "test.py", line 11, in on_message
        print 'GOT MESSAGE: {}'.format(message)
    UnicodeEncodeError: 'ascii' codec can't encode character u'\xa1' in position 0: ordinal not in range(128)
    

The character was `¡`, an upside down !. Now I know that tornado can [send
binary](http://www.tornadoweb.org/en/branch2.1/websocket.html#tornado.websocket.WebSocketProtocol8.write_message),
but apparently not receive? I am probably doing some petty mistake, but where
is it?


Answer: In the line

    
    
    print 'GOT MESSAGE: {}'.format(message)
    

you advise Python to format a character string into a byte string, which fails
if the character string contains non-ASCII characters. Simply use a character
string (prefixed with `u` in Python 2.x) instead (parentheses optional):

    
    
    print (u'GOT MESSAGE: {}'.format(message))
    #      ^
    

Alternatively, if you want to inspect binary characters, use
[`repr`](http://docs.python.org/2/library/functions.html#func-repr):

    
    
    print ('GOT MESSAGE: {}'.format(repr(message)))
    #                               ^^^^^       ^
    

