WebSocket support for Flask. What makes this extension different than others is that it does not require a greenlet based server (gevent, eventlet) to work.
This WebSocket implementation is compatible with the Flask development web server. For a production deployment it can be used with Gunicorn, Eventlet or Gevent.
The code (minimal example that simply closes websocket connections immediately upon creation): ```python3 import flask import flask_sock import eventlet from eventlet import wsgi
eventlet.monkey_patch()
app = flask.Flask(name) sock = flask_sock.Sock(app)
@sock.route('/websocket') def websocket(ws): ws.close()
if name == 'main':
wsgi.server(eventlet.listen(("127.0.0.1", 5055)), app)
To test a connection:
wscat --connect 'ws://localhost:5055/websocket'
It gets disconnected (as we expect), but if you run it again a long error is printed in the Python output:
(1572383) wsgi starting up on http://127.0.0.1:5055
(1572383) accepted ('127.0.0.1', 51362)
127.0.0.1 - - [12/Mar/2023 17:33:25] "GET /websocket HTTP/1.1" 200 0 0.001137
(1572383) accepted ('127.0.0.1', 51378)
Exception in thread Thread-1 (_thread):
Traceback (most recent call last):
File "/home/wmww/.local/lib/python3.10/site-packages/eventlet/greenio/base.py", line 364, in _recv_loop
self._read_trampoline()
File "/home/wmww/.local/lib/python3.10/site-packages/eventlet/greenio/base.py", line 332, in _read_trampoline
self._trampoline(
File "/home/wmww/.local/lib/python3.10/site-packages/eventlet/greenio/base.py", line 211, in _trampoline
return trampoline(fd, read=read, write=write, timeout=timeout,
File "/home/wmww/.local/lib/python3.10/site-packages/eventlet/hubs/init.py", line 159, in trampoline
return hub.switch()
File "/home/wmww/.local/lib/python3.10/site-packages/eventlet/hubs/hub.py", line 313, in switch
return self.greenlet.switch()
eventlet.hubs.IOClosed: [Errno 107] Operation on closed file
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "/usr/lib/python3.10/threading.py", line 1016, in _bootstrap_inner self.run() File "/usr/lib/python3.10/threading.py", line 953, in run self._target(self._args, *self._kwargs) File "/home/wmww/.local/lib/python3.10/site-packages/simple_websocket/ws.py", line 160, in _thread in_data = self.sock.recv(self.receive_bytes) File "/home/wmww/.local/lib/python3.10/site-packages/eventlet/greenio/base.py", line 370, in recv return self._recv_loop(self.fd.recv, b'', bufsize, flags) File "/home/wmww/.local/lib/python3.10/site-packages/eventlet/greenio/base.py", line 367, in _recv_loop raise EOFError() EOFError 127.0.0.1 - - [12/Mar/2023 17:33:28] "GET /websocket HTTP/1.1" 200 0 0.000883 ``` What's the cause of this, and can it be prevented or safely ignored?
flask version: 2.2.3 flask-sock version: 0.6.0 eventlet version: 0.33.3
after sometime time, emitting becomes veryyy slow and affects the entire webserver. the only fix i've found to this is restarting after an interval.
I tried copying your example (https://blog.miguelgrinberg.com/post/add-a-websocket-route-to-your-flask-2-x-application) and it just spams the page with this rendering the entire browser unresponsive. Any idea why?
How do I deploy flask-scok application with ssl? What changes should be made?
Hi, my understanding is that this only works with the Flask dev server, and with gunicorn.
How can one extend this to work with uwsgi
too?
I got flask-socketio
working with uwsgi
(and gevent
) doing something like:
uwsgi --module app:app --touch-reload app.py --master --http :8000 --http-websockets --gevent 1024
but (unsurprisingly) the same thing doesn't work with flask-sock
, probably because support for uwsgi
needs to be specifically implemented. (But how?)
Hi Miguel,
i have an issue with flask-sock in an containerized application. As I tested my app in a local environment, everything works as expected, the javascript in my html-doc connects properly and the communication runs continuously.
But now I switched to an containerized environment using gunicorn as webserver started by supervisor and now the server returns always a 404 as the html doc calls the websocket. I tried several configs to figure out what's happening, but I have no more ideas what to do.
Here are the crucial parts of code, config and log:
app.py ```python ... app = flask.Flask( name, static_folder = '/www/static' )
ws = flask_sock.Sock() ...
def create_app(): ... app.config['SOCK_SERVER_OPTIONS'] = { 'ping_interval' : 5 } ... ws.init_app(app) ... from .views import default ... return app ```
default.py
python
@ws.route('/api/ws')
def wsapi(ws):
app.logger.info('ws call')
while True:
time.sleep(1)
ws.send('Hello')
app.logger.info('ws cycle')
index.html ```javascript const ws = new WebSocket('ws://'+location.host+'/api/ws');
ws.addEventListener('open', ev => {
console.log('WS OPENED!');
});
ws.addEventListener('close', ev => {
console.log('WS CLOSED!');
});
ws.addEventListener('message', ev => {
console.log(ev.data)
});
```
supervisord.conf
...
[program:gunicorn]
command=/www/venv/bin/gunicorn wsgi:app -b :80 --reload -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker --workers 4 --threads 100
directory=/www/app
user=www-data
group=www-data
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
...
log (generated with app.before_request & app.after_request)
[2022-05-12 08:23:59,915] INFO in app: <Request 'http://10.1.7.3:9500/api/ws' [GET]>
[2022-05-12 08:23:59,917] INFO in app: <Response streamed [404 NOT FOUND]>
Maybe you have some hints for me, how to use your flask-extension properly.
Cheers, Carsten