Realtime chat with flask, socket.io and angular

Recently I started making web applications using python. Given I am so unfamiliar with the frameworks available and that I’ve always wanted to learn how to do realtime applications with socket.io, I thought was a good idea to try to make a chat with flask, socket.io and angular as an exercise.

The back-end

So socket.io is a library that enables event-based communication between clients and a server. For this chat application, I thought the simplest thing would be to handle three different events:

To handle the first two events, this is how my code looked like:

While working on this, I struggled with Cross-Origin Resource Sharing (CORS) until I realized that I needed to add the SocketIO(app, cors_allowed_origins="*") in addition to CORS(app) .

@socketio.on('sign_in') will get triggered when someone signs in. The client will send an object with the property “name” and the request will include the “socket id” in request.sid . I thought the easiest way to track the signed in users was to store them in a dictionary where the socket.id will be the key and the user name the value user[request.sid]=user_name['name'] . Once someone signs in, then I just emit the event “current_users” and send the users dictionary to all the clients.

@socketio.on('disconnect') will get triggered when someone disconnects and will delete delete the user from the users dictionary with users.pop(request.sid,'No user found') (the “No user found” is just a convenience so this doesn’t throw an error if request.sid doesn’t exist in the dictionary). Once the users dictionary is updated, we will emit the “current_users” event again with the update list to all clients.

Now that we have a system to track users, lets handle receiving and sending messages:

The above code will receive and emit messages. Here, I am leveraging the fact that each client joins a socket.io room with their respective socket ids by default . Here I am emitting to two rooms, the room from the sender and the room from the receiver. Basically that means that a client will be receiving all the messages through the same room (that has its socket id), so I will let the front-end to handle how messages received from different users are displayed (I used a filter pipe in the front-end).

But that is everything needed for the back-end. The full code looks like this:

Front-end

The Angular front-end is a bit convoluted to be described here. But briefly, I am using two services: The LoginService (login.service.ts ) and the ChatService (chat.service.ts ) . The LoginService handles the sign_in event:

The login() function will emit the ‘sign_in’ event and send the user details to the server. The server will then add this new user to the users dictionary and let all the clients know about this new user by emitting the ‘current_users’ event with the update users dictionary.

Finally, the ChatService handles the rest of the events for the chat:

The getUsers() function returns an observable which I subscribe to keep track of the connected users. Similarly, getMessage() returns an observable to keep track of all the messages sent to the client. The sendMessage() function will emit the ‘message’ event and send along the message which is a JSON object with details of which client this message should be sent to.

The final product, is a very simple chat application and a very good learning experience for me:

The full code is here.

I am a statistical geneticist. In my spare time I enjoy learning new web technologies.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store