This is a simple WebSocket server written in Python using Flask + gevent-websocket.
Inspired by https://devcenter.heroku.com/articles/python-websockets and https://github.com/kennethreitz/flask-sockets
The middleware is not Flask specific, it can be used around any WSGI application.
The server uses Redis Pub/Sub subsystem to ensure that all connected clients recieve the message, even if there are several Gunicorn workers/machines:
$ gunicorn chat:websockets --config=gunicorn_settings.py --workers=2 --worker-connections=2
2015-01-03 11:09:03 [30648] [INFO] Starting gunicorn 19.1.1
2015-01-03 11:09:03 [30648] [INFO] Listening at: http://127.0.0.1:5000 (30648)
2015-01-03 11:09:03 [30648] [INFO] Using worker: websocket_channels.Worker
2015-01-03 11:09:03 [30653] [INFO] Booting worker with pid: 30653
2015-01-03 11:09:03 [30654] [INFO] Booting worker with pid: 30654
2015-01-03 11:09:08 [30653] [INFO] Pusblishing message to channel chat: {"handle":"","text":"test"}
2015-01-03 11:09:08 [30654] [INFO] Sending message to clients on channel chat: {"handle":"","text":"test"}
2015-01-03 11:09:08 [30653] [INFO] Sending message to clients on channel chat: {"handle":"","text":"test"}Running the server:
$ gunicorn chat:websockets --config=gunicorn_settings.pyYou can send a message to a channel (after visiting http://127.0.0.1:5000/channel/users/1 ) using an HTTP POST request:
$ curl 'http://localhost:5000/publish' -d '{"users/1": "Hi user 1!"}'You can send a message to all sub-channels using trailing slash:
$ curl 'http://localhost:5000/publish' -d '{"users/": "Hi to all users!"}'Sample Nginx conf:
upstream websocket {server127.0.0.1:5000;}server{
...
location~ /ws/(?<rest>.+){proxy_passhttp://websocket/$rest;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "Upgrade";}}Then in Chrome Console you could do something like:
>$.getScript('//rawgit.com/joewalnes/reconnecting-websocket/master/reconnecting-websocket.js');<Object{readyState: 1,getResponseHeader: function,getAllResponseHeaders: function,setRequestHeader: function,overrideMimeType: function…}> var socket = new ReconnectingWebSocket("ws://"+ location.host + "/ws/channel");
<undefined> socket.onmessage = function(message) {console.log(message.data);};
<function(message){console.log(message.data);}And send a message to the browser:
$ curl 'http://localhost:5000/channel' -d '{"text": "Hi there!"}'