Flask-SocketIO needs your help!

Posted by
on under

Some of you know that for the last few weeks I have been quietly but steadily working on a significant new release of Flask-SocketIO that will be labeled 1.0, and that is practically a complete rewrite. Given that this is a fairly popular extension, I would like to ask existing users to test it and provide feedback before it is officially released.

What Is Changing?

A lot of things are changing under the hood in 1.0, and inevitably a few things are also changing in the public interface. However, I expect most existing applications will require little or no changes to run on the 1.0 release.

The big change is in the dependencies. Flask-SocketIO has depended on gevent-socketio to provide the Socket.IO server, and this was problematic because this project hasn't been updated in a long time, forcing users to work with a very old Javascript client. I have dropped gevent-socketio and replaced it with two new packages written by myself, called python-engineio and python-socketio. These packages provide the Socket.IO server-side functionality, now using current versions of the Engine.IO and Socket.IO protocols.

The heavy dependency on gevent has also been removed. In this new version you can choose to use eventlet, gevent or a plain old WSGI web server such as Werkzeug. Out of these three options, eventlet is currently the most complete implementation, with support for the HTTP long-polling and WebSocket transports. The other options only support long-polling at this time.

As a nice side effect of these changes, I can now offer support for Python 3, and since eventlet is very stable on both Python 2 and Python 3, that means that you can use the current Socket.IO client, with the WebSocket transport, on Python 2.7, 3.3 or 3.4.

Here is a more complete list of changes in version 1.0, extracted from the documentation:

  • Release 1.0 drops support for Python 2.6, and adds support for Python 3.3, Python 3.4, and pypy.
  • Releases 0.x required an old version of the Socket.IO Javascript client. Starting with release 1.0, the current releases of Socket.IO are supported (1.3.5 and 1.3.6 have been tested to work).
  • The 0.x releases depended on gevent, gevent-socketio and gevent-websocket. In release 1.0 gevent-socketio and gevent-websocket are not used anymore, and gevent is one of three options for backend web server. The other two options are eventlet, and any regular multi-threaded WSGI server, including Flask's development web server.
  • The Socket.IO server options have changed in release 1.0. They can be provided in the SocketIO constructor, or in the run() call. The options provided in these two are merged before they are used.
  • The 0.x releases exposed the gevent-socketio connection as request.namespace. In release 1.0 this is not available anymore. The request object defines request.namespace as the name of the namespace being handled, and adds request.sid, defined as the unique session ID for the client connection, and request.event, which contains the event name and arguments.
  • To get the list of rooms a client was in the 0.x release required the application to use a private structure of gevent-socketio, with the expression request.namespace.rooms. This is not available in release 1.0, which includes a proper rooms() function.
  • The recommended "trick" to send a message to an individual client was to put each client in a separate room, then address messages to the desired room. This was formalized in release 1.0, where clients are assigned a room automatically when they connect.
  • The 'connect' event for the global namespace did not fire on releases prior to 1.0, due to a problem in gevent-socketio. This has been fixed and now this event fires as expected.
  • Support for client-side callbacks was introduced in release 1.0.

Testers Wanted

If you use Flask-SocketIO, I would appreciate it if you try your application with my current working 1.0 release and provide feedback. I'm particularly interested to find out if you had to make lots of changes to your application to make it work with this version. I made every effort to minimize the changes to the public API, but I did have to make some changes.

How To Install Flask-SocketIO 1.0

I have pushed my current 1.0 version to PyPI as release 1.0a1 (Edit: current version is 1.0b1). Because it is a development version, you have to explicitly request this version to get it:

$ pip install flask-socketio==1.0b1

Or if you are upgrading an existing virtualenv:

$ pip install --upgrade flask-socketio==1.0b1

You can find the example application here: https://github.com/miguelgrinberg/Flask-SocketIO/tree/v1.0/example

If you prefer to install from GitHub, I have pushed this version to the official repository under branch v1.0.

How To Provide Feedback

You can post your comments below, or find me on Twitter or elsewhere. Just contact me in the way that is easier for you.

I appreciate your feedback!

Miguel

Become a Patron!

Hello, and thank you for visiting my blog! If you enjoyed this article, please consider supporting my work on this blog on Patreon!

59 comments
  • #51 Miguel Grinberg said

    @Wei: I'm not very familiar with sockjs, but my understanding is that feature-wise it compares with engine.io (the transport library used by socket.io). The socket.io protocol is higher level, it provides additional features such as namespaces, callbacks, etc. Also, specifically about Flask-SockJS vs. Flask-SocketIO, a brief inspection of the sockjs extension suggests there is no effort in exposing Flask context variables on the socket handlers, so my impression is that you would not have access to the user session, g, request, etc. With Flask-SocketIO all these are exposed in a somewhat similar way to normal HTTP requests (with caveats, explained in the documentation). So overall, Flask-SocketIO seems more friendly and higher level.

  • #52 Hassan Kamal said

    I faced the same problem as @cesco,
    2016-02-01 23:46:42 [13293] [ERROR] Error handling request
    Traceback (most recent call last):
    File "/usr/local/lib/python2.7/dist-packages/gunicorn/workers/async.py", line 45, in handle
    self.handle_request(listener, req, client, addr)
    File "/usr/local/lib/python2.7/dist-packages/gunicorn/workers/async.py", line 102, in handle_request
    resp.close()
    File "/usr/local/lib/python2.7/dist-packages/gunicorn/http/wsgi.py", line 369, in close
    self.send_headers()
    File "/usr/local/lib/python2.7/dist-packages/gunicorn/http/wsgi.py", line 284, in send_headers
    tosend = self.default_headers()
    File "/usr/local/lib/python2.7/dist-packages/gunicorn/http/wsgi.py", line 265, in default_headers
    elif self.should_close():
    File "/usr/local/lib/python2.7/dist-packages/gunicorn/http/wsgi.py", line 198, in should_close
    if self.status_code < 200 or self.status_code in (204, 304):
    AttributeError: 'Response' object has no attribute 'status_code'

    I am using all the updated latest packages

  • #53 Miguel Grinberg said

    @Hassan: Try adding --workers 1 to your gunicorn command line. If that doesn't help, please report your problem on stack overflow with more details regarding your environment and how to reproduce.

  • #54 Nimrare said

    If I have eventlet installed and call socketio.run(app), how can i enable SSL only and also redirect all http requests to https.

    Thanks in advance. :)

  • #55 Sukianto said

    Hi Miguel, please help me, I want to emit to my flask-socketio server

    I can emit from javascript like this:
    var socket = io.connect('http://192.168.1.5:5000/webnotif');
    socket.on('connect', function() {
    socket.emit('my broadcast event', {data: 'aaa'});
    });

    but i want to emit from my django server shell i try this:
    socketio = SocketIO(message_queue='http://192.168.1.5:5000')
    socketio.emit('my broadcast event', {'data': 'foo'}, namespace='/webnotif')

    but it return: KeyError: 'No such transport: http'

    Im running my flask-server using python app.py

    So Im not using nginx and everything else

  • #56 Miguel Grinberg said

    @Nimrare: the easiest way to do this is to put nginx in front of your server. Nginx can handle the SSL stuff and terminate it, so that your server does not need to worry about that. The alternative is to configure SSL in the eventlet server, see the eventlet docs on the wsgi server to find out how to do that.

  • #57 Miguel Grinberg said

    @Sukianto: the "message_queue" argument should be the url for your queue, not your server. You need a redis or rabbitmq server that is used for the different services to communicate.

  • #58 Harsha said

    Thank you for the great tutorials regarding flask and flask_socketio . I was trying to develop a small website using flask and socketio. I need to emit data to client side from server. But I am getting following error - "TypeError: emit() got multiple values for keyword 'room' ". Here is my code -

    value = json.dumps(metadata)
    socketIO.emit('stats', value, '/analyze')

    metadata is a dictionary, At my client side I have initialized namespace as 'analyze'

  • #59 Miguel Grinberg said

    @Harsha: you may want to write a question on stack overflow about this, and include the full stack trace of the error.

Leave a Comment