Serveur de chat

Tous les éléments sont réunis pour concevoir notre plateforme de clavardage. Avant toute chose, il convient de définir le protocole de communication entre le client et le serveur.

Convention

Les événements émanant du client seront préfixés par le caractère > alors que ceux provenant du serveur seront préfixés par <.
Nom Paramètre Définition Réponse possible
>signin pseudo Demande de connexion <connected
<error
<notification
>message texte Envoi d'un message au serveur <message
<connected pseudo Confirmation de connexion
<error message d'erreur Échec de connexion
<notification texte Envoi d'une notification aux clients
<message expéditeur + texte Envoi d'un message aux clients

Demande de connexion

Côté client

Exercice

Ajoutez un écouteur d'événement submit au formulaire signin afin :

  • d'envoyer un événement de type >signin au serveur avec comme paramètre la valeur du champ de saisie nommé nickname
  • d'empêcher la soumission du formulaire

Côté serveur

Les sockets déjà connectés sont stockés dans l'objet registeredSockets avec comme clé le pseudo de l'utilisateur. Lorsque le serveur reçoit une nouvelle demande de connexion, il doit vérifier si le pseudo est déjà attribué.

Ajoutez la création de la variable registeredSockets dans le fichier server.js

let registeredSockets = {};

Exercice

Écrivez une fonction function isAvailable(nickname) qui retourne un booléen indiquant si le pseudo est disponible ou pas.

Confirmation de connexion

Côté serveur

Si le pseudo proposé par le client lors de l'envoi de l'événement >signin est disponible, le serveur doit confirmer la connexion au client et informer tous les autres.

Exercice

Écrivez un écouteur d'événement >signin pour l'objet socket afin :

  • d'ajouter ce nouveau socket à l'objet registeredSockets
  • d'envoyer un événement de type <connected au client
  • d'envoyer un événement de type <notification à tous les autres

Côté client

L'interface Web du client chat doit être mise à jour en fonction des événements émis par le serveur.

Exercice

Écrivez deux écouteurs d'événement pour l'objet socketClient afin :

  1. <connected
    • de masquer le formulaire signin
    • d'ajouter le pseudo comme contenu textuel de l'élément span du formulaire send
    • d'afficher le formulaire send
    L'utilisateur o.nocent est connecté
  2. <notification
    • Ajouter le message passé en paramètre dans l'élément div#display
    L'utilisateur o.nocent a reçu une notification du serveur

Echec de connexion

Côté serveur

Exercice

Complétez le code de l'écouteur d'événement >signinpour l'objet socket afin d'envoyer un événement de type <error au client concerné.

Côté client

Exercice

Écrivez un écouteur d'événement de type <error pour l'objet socketClient afin :

  • de renseigner le message d'erreur dans l'élément div.toast-error
  • d'afficher l'élément div.toast-error
Le pseudo o.nocent est déjà utilisé

Envoi/réception de messages

Côté client

Exercice

Ajoutez un écouteur d'événement submit au formulaire send afin :

  • d'envoyer un événement de type >message au serveur avec comme paramètre la valeur du champ de saisie nommé message
  • de vider le champ de saisie nommé message
  • d'empêcher la soumission du formulaire

Côté serveur

Lors de la réception d'un événement >message, le serveur doit pouvoir déterminer le pseudo de l'utilisateur à partir de l'objet socket.

Exercice

Écrivez une fonction function getNicknameBy(socket) qui retourne le pseudo de l'utilisateur correspondant à l'objet socket passé en paramètre.

Le paramètre de l'événement <message envoyé par le serveur à tous les clients connectés sera un objet composé de deux propriétés : sender et text.

Exercice

Écrivez un écouteur d'événement >message pour l'objet socket qui enverra un événement de type <message à tous les clients connectés (y compris l'expéditeur initial).

Côté client (encore)

Dernière étape de l'envoi/réception de message, le client doit mettre en forme l'événement <message envoyé par le serveur.

Exercice

Écrivez un écouteur d'événement de type <message pour l'objet socketClient afin d'afficher le message dans l'élément div#display

aperçu du client chat
Mise en forme d'une conversation avec horodatage des messages

Astuce

La méthode toLocaleDateString() permet de personnaliser le format d'affichage d'une date.

Injection de code HTML

Si l'on n'y prend pas garde, un utilisateur peut injecter du code HTML via le champ de saisie send et modifier l'affichage des messages.

Injection de code HTML dans le champ de saisie des messages
Résultat lors de l'affichage dans l'élément div#display

Afin d'empêcher ce genre d'actions, il est préférable de remplacer les caractères problématiques par leur entité HTML. Le module npm ent propose une solution assez simple.

Déconnexion

Côté serveur

Exercice

Ajoutez un écouteur d'événement de type disconnect à l'objet socket afin :

  • de supprimer ce socket de l'objet registeredSockets
  • d'envoyer une notification aux autres utilisateurs