How to use Flask-Sockets? Getting a KeyError: 'wsgi.websocket'

kramer65 picture kramer65 · Nov 20, 2013 · Viewed 9.9k times · Source

I'm trying to use Flask-Sockets with the example code:

sockets = Sockets(app)

@sockets.route('/echo')
def echo_socket(ws):
    while True:
        message = ws.receive()
        ws.send(message)

Unfortunately, when simply going to the url /echo using my browser it gives me an error saying:

File "/Library/Python/2.7/site-packages/Flask-0.10-py2.7.egg/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/Library/Python/2.7/site-packages/flask_sockets.py", line 37, in __call__
environment = environ['wsgi.websocket']
KeyError: 'wsgi.websocket'

Anybody any ideas what I'm doing wrong? All tips are welcome!

[EDIT] @jbub - Thanks for the tips! So to start off I now use gunicorn instead of the built-in dev-server. So I started it using gunicorn -k flask_sockets.worker -b 0.0.0.0:5000 main:app. I then inserted the code below in my views.py i nwhich the echo_test.html is the code you supplied. When I now visit /echo_test, I indeed get a prompt saying "socket closed".

sockets = Sockets(app)

@sockets.route('/echo')
def echo_socket(ws):
    while True:
        message = ws.receive()
        ws.send(message)

@app.route('/echo_test', methods=['GET'])
def echo_test():
    return render_template('echo_test.html')

But let's say my aim is to have a word (randomly chosen from a list) on a page which gets updated with other values randomly chosen from the list. Would you have any tips on achieving that?

Answer

jbub picture jbub · Nov 20, 2013

Ah, thats the problem, you cant just visit the websocket endpoint with regular GET request, that way the wsgi.websocket will not be set to environ.

Also use gunicorn not the dev server, it comes with preconfigured worker:

# install from pip
pip install gunicorn

# run app located in test.py module (in test.py directory)
gunicorn -k flask_sockets.worker test:app

I made quick example here, be sure to update the address and port to match your setup.

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript">
       var ws = new WebSocket("ws://localhost:8000/echo");
       ws.onopen = function() {
           ws.send("socket open");
       };
       ws.onclose = function(evt) {
           alert("socket closed");
       };
    </script>
  </head>
</html>

That way the browser sends a request to the server, indicating that it wants to switch protocols from HTTP to WebSocket.

Feel free to read some more about websockets here: