0

I'm having trouble running Flask & SocketIO with Eventlet despite using socketio.run(), any suggestions are appreciated. I'm currently on Python 3.9 and I've tried multiple different versions of each of these modules with no avail.

[2021-04-04 06:39:05,709] WARNING in __init__: Flask-SocketIO is Running under Werkzeug, WebSocket is not available.
"GET /socket.io/?EIO=4&transport=websocket HTTP/1.1" 400 -

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>SAR</title>
    <script src="https://cdn.socket.io/3.1.3/socket.io.min.js" integrity="sha384-cPwlPLvBTa3sKAgddT6krw0cJat7egBga3DJepJyrLl4Q9/5WLra3rrnMcyTyOnh" crossorigin="anonymous"></script>
</head>
<body>

<button id="ping" onclick="send()">ping</button>

<script>
    var socket = io.connect("http://" + document.domain + ":" + location.port, {transports: ['websocket']});

    socket.on("connect", function(){
        socket.emit("ping", "Established a connection, pinging!");
    });

    socket.on("pong", function(response){
        console.log(response)
    });

    function send(){
        socket.emit("ping", "ping_data");
    }
</script>

</body>
</html>

app.py

from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import eventlet

app = Flask(__name__)
socketio = SocketIO(app, logger=True)

@app.route( '/' )
def index():
  return render_template( 'index.html')

def receivedCallback():
  print('Pong received by user!')

@socketio.on( 'ping' )
def handle_ping(data):
  print("received", data)
  socketio.emit('pong', "pong_data", callback=receivedCallback)

if __name__ == '__main__':
  socketio.run(app)
Skel
  • 11
  • 1

2 Answers2

1

It seems like running my main file through the terminal resolves this issue. If anyone knows why this is please do share, thanks. :)

python app.py

Skel
  • 11
  • 1
0

To give a loose idea of why it runs with python app.py is that the if __name__ == '__main__' is executed only when it is run through the terminal, much like how the main function is called first in many other programming languages like Java or C when run from the terminal directly.

When a Flask app is run through Werkzeug, the flask app instance is imported and sort of wrapped into a module by Werkzeug in which the requests are routed into. (That is why the if __name__ == __main__ part is never executed – much like when you import another module in your code, the main function of that module is never called.) So, as far as my understanding goes, when you run your Flask app through Werkzeug, the requests are received and routed over HTTP by default and not over the WebSocket protocol that Flask-SocketIO uses when you run socketio.run(). The WebSocket protocol requires a socket to be always open, enabling asynchronous I/O which cannot work in HTTP as it is a client-server protocol.

I, however, do not have an answer to how to solve the problem and work with Flask-SocketIO through Werkzeug, but I hope the above explanation throws some light into your problem and drives you in the correct direction to look at.

Shornabho
  • 21
  • 1