WebSocket connection between reactjs Client and flask-socketio Server doesn't open

8.6k Views Asked by At

In my project I am using a React front-end and a Flask server with a RESTful API. The basic functionality is that the front-end fetches data from the server and displays it. This works fine, but I figured I'd improve upon it by making the client automatically re-fetch whenever the server receives new data from elsewhere. I could use polling and just fire off a fetch request in intervals, but this seems like the perfect use case for WebSockets. As such, I'm trying to implement a websocket connection between the server and client in which the server sends a message to the client when certain events happen.

My server is written in python with Flask, and it seemed like a good idea to use a websocket library specific to Flask. I ended up using flask-socketio, but I've been having problems making it work. The relevant parts of my server is as follows:

from flask_socketio import SocketIO, emit

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)

... # Server functionality for receiving and storing data from elsewhere, not related to the websocket

# Handle the webapp connecting to the websocket
@socketio.on('connect')
def test_connect():
    print('someone connected to websocket')
    emit('responseMessage', {'data': 'Connected! ayy'})


# Handle the webapp connecting to the websocket, including namespace for testing
@socketio.on('connect', namespace='/devices')
def test_connect2():
    print('someone connected to websocket!')
    emit('responseMessage', {'data': 'Connected! ayy'})


# Handle the webapp sending a message to the websocket
@socketio.on('message')
def handle_message():
    print('someone sent to the websocket')


# Handle the webapp sending a message to the websocket, including namespace for testing
@socketio.on('message', namespace='/devices')
def handle_message2():
    print('someone sent to the websocket!')


@socketio.on_error_default  # handles all namespaces without an explicit error handler
def default_error_handler(e):
    print('An error occured:')
    print(e)

if __name__ == '__main__':
    socketio.run(app, debug=True, host='0.0.0.0')

For the front end, I initially tried using a library as well. I went with react-websocket.

<Websocket
  url={'ws://localhost:5000'} // I also tried /devices at the end of this url
  onMessage={() => console.log('Received message through websocket.')}
  debug={true}
/>

However, this solution kept disconnecting immediately after connecting, implying that something was wrong. Finding out exactly what went wrong seemed impossible though; I got no indication in the logs despite debug={true}. Instead of this solution, I swapped to a more custom WebSocket solution for the front-end:

componentDidMount() {
    moment.locale('nb');
    jsonRequest(irrelevant url).then(jsonResponse => {
      ... // Handle the results of the initial fetch

      const socket = new WebSocket('ws://localhost:5000'); // I also tried /devices at the end of this url

      socket.onopen = () => console.log('opened custom socket');
      socket.onclose = () => console.log('closed custom socket');
      socket.onmessage = e => console.log('got message');
      socket.onerror = e => console.log('websocket error');
      socket.addEventListener('open', function(event) {
        console.log('sending');
        socket.send('Hello Server!');
      });
      socket.addEventListener('message', function(event) {
        console.log('Message from server ', event.data);
      });
      this.socket = socket;

      this.setState(...);
    });
}

This solution has the same problem. My console output is as follows: console output

The Rendering... is a console statement i put at the very top of my render function.

So in both solutions, the client immediately disconnects from the websocket connection after connecting. My server also doesn't notice anything. None of the event handlers trigger - not @socketio.on('connect'), not @socketio.on('message') and not even @socketio.on_error_default. As such, I find myself at a roadblock. How do I debug from here? What could the issue be? I have tried the same exact code on an Ubuntu server, so I don't think localhost is the issue.

1

There are 1 best solutions below

0
On BEST ANSWER

You are confusing Socket.IO with WebSocket. The Socket.IO protocol is built on top of WebSocket and HTTP. Your connection failures result from you using a plain WebSocket client to connect to a Socket.IO server. You need to use a Socket.IO client, like this one.