Search code examples
pythonpython-3.xflasksocket.ioflask-socketio

Flask-SocketIO running app but not firing events


So I'm building a simple Flask social media application that uses Flask's session ids. I want to remove a user's session id whenever they leave the page so that they have to re-login. I did a little research and found out that Flask-SocketIO allows you to do that through the 'connect' and 'disconnect' events. However, when I run the app, and I open up the site/log on to the page, nothing happens. I don't get any output from the connect event nor the disconnect event when I close the tab. Here's the full code.

# Starting/Initialisation of App
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = SECRET_KEY
socket_io = SocketIO(app=app, logger=True, engineio_logger=True)
db = SQLAlchemy(app)

# Socket IO Events
@socket_io.on('connect')
def on_connect():
    print("Connected!")

@socket_io.on('disconnect')
def on_disconnect():
    # TODO Fix this socket io disconnect event. It's not working for some reason. Just figure things out with socketio
    print("Client Disconnected")
    print("YOOOOOOOOOO")
    session.pop('id')

@socket_io.on('message')
def on_message():
    print("Exit message")

# App Routes
# A page where a user can login to an account
@app.route('/', methods=['GET', 'POST'])
def index():
    # If user submits form
    if request.method == "POST":
        # Get response and user's Account object from db
        # if query does not return None aka user is in database
        # Check if response's password is the same as the user's password
        # If it is, redirect to homepage
        # Else if not, return an "invalid password" error

        form = request.form # User Response
        user = Account.query.filter_by(email=str(request.form['email'])).first() # Query for user

        if user is not None: # Validating query
            if str(form['password']) == user.password: # Checking password
                session['id'] = user.id
                return redirect('/home')
            else:
                return "Invalid password"
        else:
            return "Invalid email or password"
    else:
        return render_template('index.html')

# Run App
if __name__ == '__main__':
    socket_io.run(app)

I'm don't receive any errors or whatsoever so I'm really confused.

Below is my pip freeze

bidict==0.21.2
click==8.0.1
colorama==0.4.4
Flask==2.0.1
Flask-SocketIO==5.1.0
Flask-SQLAlchemy==2.5.1
greenlet==1.1.0
h11==0.12.0
itsdangerous==2.0.1
Jinja2==3.0.1
MarkupSafe==2.0.1
python-engineio==4.2.0
python-socketio==5.3.0
simple-websocket==0.2.0
SQLAlchemy==1.4.22
Werkzeug==2.0.1
wsproto==1.0.0

Would really appreciate it if anyone has any solutions to this. Thanks in advance.


Solution

  • Few things to consider here:

    1. print statements to stdout won't necessarily show in your output with Flask, I believe stderr does, so you might want to try either that or the logger, e.g.:
    print('Connected!', file=sys.stderr)
    app.logger.info("Connected!")
    
    1. Are you sure you have the right version of the client? I don't believe the client is included with Flask-SocketIO, and Flask-SocketIO isn't compatible with the latest client version (4). You should be using client version 3.1.3 (https://socket.io/docs/v3/). This is the version of the SocketIO library you include (this example truncated from the aforementioned SocketIO docs and updated to show an alert box once connected so you can be sure it's worked):
    <html>
    <body>
    ...
    <script src="https://cdn.socket.io/3.1.3/socket.io.min.js" integrity="sha384-cPwlPLvBTa3sKAg    ddT6krw0cJat7egBga3DJepJyrLl4Q9/5WLra3rrnMcyTyOnh" crossorigin="anonymous"></script>
    <script type='text/javascript'>
    const socket = io("ws://localhost:5000");
    
    socket.on("connect", () => {
      // either with send()
      alert("You're connected!");
      socket.send("Hello!");
    
      // or with emit() and custom event names
      socket.emit("salutations", "Hello!", { "mr": "john" }, Uint8Array.from([1, 2, 3, 4]));
    });
    </script>
    </body>
    </html>
    
    1. does your web console in your browser show any errors? Are you sure the client side code is correct and you're connected? Viewing the Javascript console varies from browser to browser, but will show you any errors encountered in your Javascript. In Chrome for example, you click the 3 dots to the far right of your address bar, then More Tools -> Developer Tools. This is cruicial in debugging Javascript issues.