flask-uwsgi-websocket
flask-uwsgi-websocket copied to clipboard
How can I send something to a specific websocket in my application from another function?
Imagine this:
@websocket.route("/websocket")
def my_websocket(ws):
ws.send("foo")
@app.route("/somewhere")
def somewhere():
#ws.send("bar")
Is this way of working at all possible with websockets? Do I instead need some kind of internal message spooler in my_websocket that I send stuff to which in return sends it to the client? Or can I somehow do this more conveniently as I outlined in my example?
If it's a single instance, you can just keep a set of connections. Otherwise you should use redis or something like that for pub/sub.
Can you post up a snippet? I tried keeping connections in a global list but that didn't work out so well.
I would personally use redis pub/sub for this. Subscribe to an event (for example "send-to-ws") when the websocket connects. Then publish that event in the "somewhere" route. This way you don't need global lists and it scales great.
You can use Flask-Redis and redis-py for this: https://github.com/underyx/flask-redis https://github.com/andymccurdy/redis-py
Use the redis.pubsub()
method.
I wouldn't try to keep connection instances in a global, because those won't be shared across instances, if you for example run uWSGI with several workers.
When I try to do something like:
@app.route("/ready")
def ready():
ws.send("message")
return ""
It seems to send nothing through the websocket and instead sends "message" to the browser that requested /ready.
If you are running one instance of the app (not multiple, like when you use uWSGI), something like this should work:
app = Flask()
websocket = WebSocket(app)
clients = {}
@websocket.route('/connect')
def connect(ws):
clients[ws.id] = ws
# keep listening for messages until the connection is closed
while ws.connected is True:
message = client.receive()
# the client is removed when the websocket connection is closed
del clients[ws.id]
@app.route('/send_all_websockets')
def send_all_websockets():
""" send a message to all connected websockets """
for id, client in clients.iteritems()
client.send('hello')
But again, this will only work when running as one instance. This is also basically what happens in the chat example: https://github.com/zeekay/flask-uwsgi-websocket/blob/master/examples/chat-gevent/chat.py
Ahh, that's pretty much exactly what I did, I had figured it was a problem with doing it through uWSGI, that at least gives me somewhere to look, thanks!
...really should add another example to cover this (extremely common) use case.