Designing An Online Chatting Application

A gif of two users chatting with each other.
Gif of two users chatting with each other.

I developed a web-based chat application where multiple people can communicate through text over the internet for an open-ended website development final project in college.

You can try out this chat program, hosted at kimpampusch.tech/chat.

Link to source

Chatting

The easiest way to test the chatting functionalities is to open the webpage up on two different devices to chat with yourself.

If you have an opportunity that you wish to discuss with me, contact me and you can request that we have a preliminary discussion using this web chat.

The Database

Image of the chat database layout.

The chat data is stored in a database that consists of three tables: users, events, and messages.

users is made up of a unique primary key id, a unique name, a tinyint representing a boolean, is_active, and a record of when the user was last active, last_timestamp.

The events table has a unique primary key id, an enum (‘user_joined’, ‘user_left’, ‘message_sent’) representing the type of event, type, a foreign key to the associated element in the users table, user_id, and a timestamp for when the event occurred, timestamp.

messages contains a unique primary key id, a foreign key, event_id, relating the message to the appropriate event, and a text, message.

Interfacing With The Database

The chat page made heavy use of AJAX to request the server update the database and return some information. AJAX was used during several client events:

  • When the client page loads – Update the database with the user info and insert a ‘user_joined’ event to the events table.
  • When the client sends a message – Insert a ‘message_sent’ event and insert the appropriate message to the messages table (shown below).
  • Several times a second in the background – Check for new events and update the client’s webpage accordingly

The following php code was used as an AJAX request to have the server update the database when the client sent a new message.

<?php
// Initialize $conn
require 'sqlInterface.php';
global $conn;

$username = mysqli_real_escape_string($conn, $_POST['username']);
$message = mysqli_real_escape_string($conn, $_POST['message']);
    
$query = "
BEGIN;
INSERT INTO `events`(`type`, `user_id`) 
    VALUES ('message_sent', (SELECT `users`.`id` FROM `users` 
    WHERE `users`.`name` = '".$username."'));
INSERT INTO `messages`(`event_id`, `message`)
    VALUES (LAST_INSERT_ID(), '".$message."');
COMMIT;
";
mysqli_multi_query($conn, $query) or die(mysqli_error($conn));
?>

Making This Work With Chrome

Whenever the client leaves the chat page, the webpage has to add a ‘user_left’ event and update the user to be inactive. This was done with AJAX, similar to the examples in the previous section. I had done most of my testing with Firefox and when testing cross-browser functionality I found that Google Chrome ignores AJAX requests sent when the page is unloading.

To make this request work on Chrome, I had to use another method to send a request when unloading the page, navigator.sendBeacon

navigator.sendBeacon(url, data);

This method was made specifically for the purpose of sending data to the server when a page was being unloaded, but this still didn’t update the database with Chrome.

An image of the request header in Chrome DevTools.
Image of request header in Chrome DevTools.

I could see that a request was being sent out by viewing the Chrome DevTools, but the issue was with the content type Content-Type: “text/plain;charset=UTF-8”

This script required data from the website to update the database correctly, but the expected content type was Content-Type: “application/x-www-form-urlencoded; charset=UTF-8”

In Chrome, navigator.sendBeacon is limited in possible Content-Types due to security issues. When sending out the request with the specified content type, Chrome modified the header. This made it so the php script could not read the data I sent with the request, and could not operate correctly.

To make this work, I changed the request to always use Content-Type: “text/plain;charset=UTF-8”, and then I altered the php script to use this content type.

Kim is a self-taught programmer in the Minnesota area. Kim currently works as a full-stack developer while working on various crafts. Kim always has time to make a couple of loaves of bread.