WhiiTe'

Administateur
Ancien staff
Inscription
22 Octobre 2011
Messages
14 706
Réactions
8 492
Points
32 425
header.png


Bonjour à tous,

Dans ce tutoriel je vais vous apprendre à réaliser un chat instantae en utilisant NodeJs et Socket.io.
Je vais partir d'une page vierge, il n'y aura donc pour le moment aucun design.
Je suis sous Windows 7, il est possible que le tutoriel ne sera pas adapté à votre système d'exploitation, je parle surtout pour les commandes, à vous de voir comment faire sur votre machine ou de faire certaines choses à la main, si c'est possible.

Vous allez tombé au bout d'un moment sur des commentaires numérotés , je vous conseille d'avance de ne pas y toucher, ceux-ci permettront de vous repérer entre le code et là où je vous dirai de mettre du code.

Si je me trompe dans certains termes, n'hésitez pas à me le dire, il est probable que j'emploie un terme incorent ou complétement hors sujet.

Je réaliserai le tutoriel en local, mais une fois que vous aurez tout le code, vous pourrez l'utiliser en ligne avec un VPS .

nodejsinstall.png


Avant de pouvoir faire du NodeJs, il faut l'installer. Rendez-vous donc sur et téléchargez le.
Mettez ce que vous voulez lors de l'installation, et une fois fini ouvrez le terminal et tapez :​

Code:
node
console.log("Hello world");

Si Hello world s'affiche bien, c'est que NodeJs est bien installé et donc que nous pouvons commencer.

petit-sepa.png


Nous allons commencer par initialiser notre projet.
Rendez-vous là où vous voulez, personnellement je serai sur le bureau, ensuite créez un nouveau pertoire et placez-vous dedans.
Ouvrez le terminal et rendez-y vous à l'aide de la commande cd.
Tapez ensuite la commande :​

Code:
npm init

Puis mettez ce que vous voulez.
Une fois ceci fait, vous apercevrez qu'un fichier package.json s'est crée, tout est donc bon pour le moment.

Le package.json est important si vous comptez déplacer votre projet . Car quand nous allons télécharger les librairies utiles pour le tutoriel, il y aura un dossier node_modules qui va se créer avec tout les composants nécessaires au bon fonctionnement de notre projet.

Le package.json permettra de installer toutes ces libraires avec une commande spécifique :​

Code:
npm install

Et là le dossier node_modules va se re-télécharger avec toutes les libraires indiquées dans le package.json.

Pratique non ?

Maintenant nous allons créer un fichier server.js et un dossier public, qui contiendra nos fichiers html, nos ressources CSS / Js etc...​

Code:
cd. > server.js
mkdir public

Et créer un fichier index.html à l'intérieur de ce dossier.​

Code:
cd public
cd. > index.html

Nous pouvons donc commencer notre projet.

createchat.png


Pour faire le chat, je vais utiliser socket.io et express .
Dans le terminal, tapez ces deux commandes.​

Code:
npm install --save socket.io
npm install --save express

Le --save de la commande permet d'écrire dans le fichier package.json le fait que vous utilisez une librairie, je vous conseille de le mettre à chaque fois, comme ça si vous souhaitez déplacez les fichiers à distance, vous n'aurez pas besoin d'envoyer le gros dossier node_modules.

Maintenant nous allons commencer à écrire la partie JavaScript, ouvrez avec un éditeur de texte le fichier server.js crée au préalable.

Insérez-y ce code :​

Code:
let express = require('express');
let app = express();
let server = require('http').createServer(app);
let io = require('socket.io')(server);
let port = process.env.PORT || 8080;

server.listen(port);

app.use(express.static(__dirname + '/public'));
app.get('/', (req, res) => {
    res.sendFile(__dirname + '/public/index.html');
});

// Suite du code

Premièrement on initie les variables plus ou moins utiles à notre projet, là ce n'est que le début, donc toutes ces variables sont importantes, ensuite je précise au serveur d'écouter le port 8080, qui est stocké dans la variable port, ensuite à l'aide d'epxress, je fais deux choses, je dis que tous les fichiers statiques qui sont placés dans le dossier public doivent être statique, sans ça le CSS ne fonctionnera pas, les images non plus etc.., puis je dis au serveur de rendre le fichier index.html du dossier public si la requête envoyée provient de l'index. (/)

Maintenant, rendez-vous sur .

Ça ne fonctionne pas ? C'est normal ne vous en faîte pas, NodeJS ne se lance pas tout seul, à chaque modification du fichier server.js ou quand vous voulez lancer le serveur, il faut taper cette commande :​

Code:
node server.js

Vérifiez bien que vous n'êtes pas dans le dossier public, pour faire un retour en arrière faîte ceci :​

Code:
cd ../

Rafraîchissez la page, et désormais la page devient blanche, plus d'erreur de connexion refusée ou je ne sais quoi !

petit-sepa.png


Avant de commencer la partie la plus intéressante, il faut faire la base HTML, c'est à dire un simple formulaire avec un champ pseudo et message, un ul qui contiendra les messages et une div qui affichera les erreurs.

Comme je suis sympa je vous ai préparé une base qui est comme je l'ai décrite, basique ..​

HTML:
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>NodeJs chat</title>
    </head>
    <body>
        <form>
            <input type="text" id="username" placeholder="Votre pseudonyme"><br />
            <textarea id="message" placeholder="Votre message"></textarea><br />
            <input type="submit" id="submit">
        </form>

        <div id="response"></div>

        <ul id="messages" style="list-style:none;"></ul>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
        <script src="/socket.io/socket.io.js"></script>
        <script>
            $(document).ready(function(){
                let socket = io();
                $('#submit').on('click', function(e){
                    e.preventDefault();

                    let data = {
                        username: $('#username').val(),
                        message : $('#message').val()
                    };

                    socket.emit('new message', data);
                });

                // Suite du code
            });
        </script>
    </body>
</html>

J'écrirai le code JavaScript visible en bas de la page, mais vous pouvez bien évidemment tout mettre dans un fichier JavaScript et l'inclure sur la page, ça ne posera aucun souci.

La partie JavaScript est très basique, j'initie une variable socket, je créer un événement qui, au clique du bouton, va créer une variable data qui contient le champ du pseudo et du message. Ensuite grâce à socket.io, je peux envoyer sans passer par de l'Ajax, la requête au serveur, que je vais récupérer dans le fichier server.js, je vais faire le traitement et rendre une erreur si besoin.

A la suite du code dans server.js, rajoutez ceci :​

Code:
io.on('connection', function(client){

    // commentaire 12  (pour après)

    client.on('new message', function(data){
        // Suite
    });

    client.on('disconnect', function(){
        delete client;
    });

});

Il est important de comprendre ceci, sur la première ligne nous disons que dès qu'on a une connexion , on créer une variable, que j'ai nommée client , qui va être en fait le client en lui-même, chaque client aura des propriétés différentes, tel que l'ID. (client.id)
En-dessous je supprime le client s'il se connecte .

Vous verrez que socket.io est très simple à manier, une fois que son utilisation est comprise ça ira tout seul, le code est très titif.

Vous pouvez apercevoir que je créer une sorte de listener, qui va agir quand on aura l’événement.
Pour le moment notre code se résume à :​
  • Soumission du formulaire => On émet les valeurs du formulaire
  • Côté serveur => Listener reçoit l’événement, du-coup va traiter les informations.
C'est en gros comme ça qu'il faut voir comment ça fonctionne.
Nous allons maintenant vérifier les valeurs serveur et renvoyer une erreur s'il devait y en avoir une.

A la suite mettez ceci :​

Code:
// Vérification du pseudonyme
if(!data.username || typeof data.username == undefined || data.username.length > 25){
    client.emit('error message', "Le pseudonyme rentré n'est pas valide !");
    return;
}

// Vérification du message
if(!data.message || typeof data.message == undefined || data.message.length > 255){
    client.emit('error message', "Le message rentré n'est pas valide !");
    return;
}
// commentaire 13
io.emit('new message', data);

Premièrement on regarde si on a pas de pseudo, si le pseudo est typé undefined ou s'il est supérieur à 25 caractères, si il correspond à tous ces mauvais critères, on émet au client l'erreur, il en est de même avec le message, pensez bien à chaque fois à stoppez le script en y ajoutant un return.

Si tout est bon on émet à tout le monde le message, avec les mêmes données envoyées.

Vous allez peut-être vous dire, comment envoyer un événement à un client, et non à tout le monde, c'est très simple, regardez bien le code.​
  • client.emit => Envoi uniquement au client
  • io.emit => Envoi à tout le monde même au client concerné
  • client.broadcast.emit => Envoi à tout le monde sauf au client concerné
Il y a d'autres énement, je vous laisse les chercher sur le net.
Maintenant passons côté client, à la suite du code dans votre index.html rajoutez-y ceci :​

Code:
socket.on('error message', function(phrase){
    $('#response').html(phrase);
});

socket.on('new message', function(data){
    $('#messages').append('<li>' + data.username + ' : ' + data.message + '</li>');
});

Essayez maintenant de poster un message, magique non ?

Avant de continuer plus loin, il y a un très gros souci, en effet une faille XSS est actuellement présente, si un membre vient mettre du contenu HTML, celui sera interprété et écrit en HTML, il pourra donc faire rediriger tout le monde vers une mauvaise page, ou écrire en gros, styliser la page à sa guise, bref faire ce que bon lui semble .

Voici une fonction pour remédier à ça :​

Code:
function XSSPatcher(texte){
    return texte
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&&#039;")
}

Et remplacez la ligne qui insert un nouvel élément dans la liste des messages par :​

Code:
$('#messages').append('<li>' + XSSPatcher(data.username) + ' : ' + XSSPatcher(data.message) + '</li>');

La faille XSS est désormais patchée !

recuplastmessage.png

Quand un utilisateur arrive sur la page, il tombe sur une page qui ne contient aucun message.
Je vais donc vous montrer comment stocker les 5 derniers messages grand maximum afin de les placer dans la page du nouvel arrivant.

Pour commencer, tout en haut là où nous définissons nos variables, nous allons rajouter :​

Code:
let lastMessage = new Array();

Ensuite, nous allons envoyer le tableau au client dès qu'il se connecte, à la place du commentaire nuro12, placez cette ligne :​

Code:
client.emit('last message', lastMessage);

Et maintenant à la place du commentaire 13 mettez-y ceci :​

Code:
        lastMessage.push(data.username + ' : ' + data.message);
        for(var i = lastMessage.length-1; i--;){
            if(i == 4){
                lastMessage.shift();
            }
        }

Ce code va insérer une nouvelle entrée à l'index 0 contenant le message complet à insérer par la suite, ensuite on fait une boucle qui va vérifier s'il n'y a pas plus de 5 entrées, si c'est le cas on supprime la premre entrée.

Maintenant côté client (index.html), nous allons simplement rajouter une boucle qui va récupérer toutes les entes du tableau afin de les ajouter à notre page HTML.​

Code:
socket.on('last message', function(arr){
    for(i = 0;i < arr.length;i++){
        $("#messages").append('<li>' + XSSPatcher(arr[i]) + '</li>');
    }
});

Et voilà, mettez un message, rafrchissez la page, que constatez-vous ? Eh oui les derniers messages apparaissent !

theend.png


Le tutoriel touche à sa fin, comme je l'ai dit en début il est probable que j'emploie de mauvais termes, ou de mauvaises manières de coder, n'hésitez donc pas à me le reprocher !

Si vous avez des questions, n'hésitez pas à venir en privé ou à poster vos questions dans les commentaires afin que la communau puisse vous répondre.

Si vous voulez la suite de ce tutoriel, dîtes-le moi dans les commentaires ! (membre est entrain d'écrire, membre a rejoint le salon ..)

Merci à @Louis pour le header et les parateurs.

:tchuss:
 

WhiiTe'

Administateur
Ancien staff
Inscription
22 Octobre 2011
Messages
14 706
Réactions
8 492
Points
32 425
Je fois une erreur de syntaxe notamment avec l'apostrophe et le nom de la fonction est mauvais je crois :noel6:

Le souci de syntaxe c'est un bug sur RG je pense, j'ai ça chez moi :|
Et nop c'est bien disconnect :mmh:
 
Haut