L'objectif de cette partie est de réaliser un micro-service web de dépot et d'accès à des messages texte, en utilisant NodeJS. Pour la complétude de la chose, nous utiliserons front-end de type "Message Board" réalisé lors de la partie HTML+CSS+Javascript.
Résumé des resources
Ressources sur HTML + CSS:
- Les slides sur les Markup Languages
- Les slides sur HTML+CSS
- Resources locales sur HTML et CSS.
- L'API en ligne de codage: http://www.Repl.it
Ressources sur Javascript:
- Les slides du cours sont ici : Javascript et JSclient
- Consulter les tutos Javascript, JSclient et DOM
- Ayez à portée de main la documentation de JavaScript sur Mozilla Developper Network
Les transparents du dernier cours.
Code à rendre sur Edunao
1 - NodeJS
2.1 - Configuration
Clonez le repl https://repl.it/@kindjob5578/MessageBoard.
Observez les différentes parties:
- Dans la zone "fichiers", vous avez un fichier
index.js
: c'est le code javascript exécuté par NodeJS. Il pourrait y avoir pleins d'autres fichiers. - En dessous de ce fichier, il y a les fichiers de configuration du programme NodeJS. Ils sont apparu car j'ai avant installé pour vous la librairie express. Vous pouvez en installer d'autres...
- à droite, il n'y a pour le moment qu'une console qui dit "Node" : ce n'est pas la console du navigateur mais celle du programme NodeJS.
Pour l'instant le programme ne tourne pas. Lancez le programme en appuyant sur "Run".
- Maintenant au dessus de la console vous avez la racine de votre site: son adresse (temporaire) est accessible à cet endroit.
- En dessous, vous avez toujours la console NodeJS. Le programme s'exécute: "App listening on port 8080..." s'affiche. C'est la commande de la ligne 9 dans
index.js
.
À l'inverse d'un serveur purement statique, ici vous avez les manettes pour décider de comment votre serveur réagit aux requêtes HTTP: tout se programme dans index.js
.
D'ailleurs, vous noterez que pour le moment, la page répond "Cannot GET /". Pour ce qui nous intéresse, on ne va pas créer une route /
... Vous pouvez si cela vous amuse ceci dit.
Définition d'une route
Nous allons maintenant ajouter une "route", c'est-à-dire une requête HTTP que votre application va accepter et traiter. Une route est constituée de deux éléments : un verbe HTTP (par exemple : GET, POST, PUT…) et un chemin (par exemple : /voici/un/chemin, /chemin, /un/autre/long/chemin…).
- Ajouter juste avant
app.listen(...)
la route suivante, qui définit que l'application accepte une requête GET sur le chemin/test/[quelquechose]
- On peut donc ajouter du texte quelconque après
/test/
et la route sera reconnue- Donc quelque chose comme https://l-adresse-generee-par-repl-it/test/blihblahblih]]
- On peut donc ajouter du texte quelconque après
La fonction (non-nommée) est appelée quand un client se connecte à l'adresse en question. Le corps de la fonction a accès aux deux variables passées en argument: req
et res
. Le premier contient les infos de la requête, le deuxième est l'objet réponse à construire. Il possède une méthode très utile: res.json(objet-javascript)
qui construit une réponse HTTP contenant un fichier JSON décrivant l'objet passé en argument.
- Utilisez cette méthode pour rendre un object javascript, par exemple
{"a": 1, "b" : 2}
. Dans la suite, essayez aussi avec["Hello", "World"]
. Et avec42
.- Appuyez (ou ré-appuyez) sur "Run".
- Allez à l'url de votre site en demandant la ressource "/test/quelquechose" et observez le résultat.
- Notez que le fichier JSON retourné correspond à l'objet passé en argument.
- On va maintenant utiliser ce qui est passé dans l'adresse.
- Si on a
/test/blihblah
, on veut retourner l'objet{"msg": "blihblah"}
req.url
contient la chaine "test/blihblah"- Pour une sous-chaine: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/String/substr
- Si on a
Note
Quand vous faites des changements dans index.js
, il faut "relancer" NodeJS en appuyant sur "Run"
2.3 - Un micro-service avec un état
Nous allons réaliser un micro-service maintenant un état au sein du serveur. L'état sera un entier, initialisé à zéro au démarrage du serveur.
On veut deux routes /cpt/inc
et /cpt/query
, avec les comportements suivant:
/cpt/query
: rends un fichier json avec la valeur du compteur/cpt/inc
: incrémente de 1 la valeur du compteur, retourne un fichier json avec l'objet{"code" : 0}
/cpt/inc?v=XXX
: deux cas :- XXX est bien un entier : incrémente de XXX la valeur du compteur et retourne un fichier json avec l'objet
{"code" : 0}
- XXX n'est pas un entier : ne touche pas au compteur et retourne
{"code" : -1}
- XXX est bien un entier : incrémente de XXX la valeur du compteur et retourne un fichier json avec l'objet
Vérifiez que vous pouvez incrémenter le compteur de l'un-e de vos collègue, et inversement.
Note
- On peut accèder aux arguments (ici "
v
" par exemple) à l'aide dereq.query
. Par exemple, essayez la route
et allez voir à l'address votre-serveur/blah?key1=value1&key2=value2
- Pour vérifier si une chaine de caractère correspond à une expression régulière, vous pouvez utiliser
match
. Par exemple:
rend vrai, et rend faux.
2.4 - Micro-service de gestion de messages
Avec notre serveur on souhaite pouvoir faire au minimum cinq choses:
- Ajouter un message à la liste des messages
- Récupérer un message par son numéro
- Récupérer TOUS les messages
- Récupérer le nombre de messages postés
- Effacer un message de la liste
On va donc faire 4 routes:
/msg/post/[le-message-à-poster]
/msg/get/[le-numéro-du-message]
/msg/getAll
/msg/nber
/msg/del/[le-numero-du-message]
et on va stocker les messages dans une variable sur le serveur.
Note
- Pour pouvoir tester facilement l'interface avec un navigateur, je vous propose de tout faire avec des appels GET. Poster un message serait (à terme) plus naturel avec un appel POST bien sûr.
- L'un des problème est alors le préchargement automatique des requêtes GET... Comme par exemple ce que Safari fait.
- Préférez Chrome ou Firefox pour les tests directement avec la barre d'adresse
À faire
- Créez dans
index.js
une nouvelle variable globale qui contiendra les messages:
- Créez une nouvelle route
/msg/get/*
- Supposons que le message 42 est
"FOOBAR"
. La fonction de callback correspondant à une route/msg/get/42
va renvoyer un JSON sous la forme
- Supposons que le message 42 est
- Si il n'y a pas de message 42 (ou si on a entré quelque chose qui n'est pas un entier), la fonction de callback va rendre
- Note:
parseInt()
est votre ami pour changer une chaine de caractères en entier. - À la place de
res.sendFile
, on utilise la fonctionres.json(objet-javascript)
.
- Note:
- Relancez le serveur, et testez avec votre navigateur en allant à l'adresse
http://xxx.xxx.repl.co/msg/get/2
ethttp://xxx.xxx.repl.co/msg/get/5
- De façon similaire, réalisez les autres routes:
/msg/nber
rendra simplement un entier (la taille de la liste),/msg/getAll
un tableau de string, et/msg/post/[un message]
pourra simplement retourner le numéro du nouveau message posté.- Le message contient éventuellement des caractères d'échappement (par exemple
%20
pour un espace). Vous pouvez retrouver la chaine de caractères originelle avec la fonctionunescape("hello%20world")
- Le message contient éventuellement des caractères d'échappement (par exemple
- Testez vos méthodes:
- Poster 2 messages
- Vérifiez avec un appel à
/msg/get/xxx
que vous obtenez bien le résultat attendu. - Testez de manière similaire les autres routes.
3 - Rendre le Mock-up vivant !
Notre objectif est de connecter le site de dépot de message du premier TP avec ce micro-service de gestion de messages.
Pour cela, on va faire des appels AJAX (Asynchronous Javascript XML... sauf qu'on va manipuler du JSON en fait).
3.1 - Prise en main
Nous allons faire usage de la méthode fetch
et des "promesses", comme discuté en cours. La forme du code qui va nous intéresser est comme suit:
La méthode fetch
va générer en tache de fond un appel asynchrone à l'adresse indiquée. Puis, lorsque la réponse aura été reçue, la série des then
va être exécutée:
- D'abord on récupère le json associé à la réponse
- puis on utilise le json en question
Note
On ne peut pas utiliser directement utiliser response.json()
: il s'agit d'une... promesse, à ouvrir avec le .then
qui vient après.
À faire
- Copiez-collez ce code dans le fichier
script.js
du repl de Mockup.- Changez l'adresse pour celle de votre micro-service de message, sur la route
msg/getAll
- modifier l'appel à
alert
pour récupérer le premier message
- Changez l'adresse pour celle de votre micro-service de message, sur la route
- "Lancez" la page du mockup: un pop-up avec le premier message du micro-service doit apparaitre.
3.2 - Remplissage des messages
Essentiellement, ce dont on a besoin au chargement de la page est d'ajouter les messages dans l'ordre. Vous avez réalisé cela dans le premier TP, en utilisant une variable locale.
À faire
Modifiez votre code pour peupler la liste des messages en utilisant le résultat à l'appel AJAX de votre micro-service de messages.
3.3 - Publication d'un nouveau message
Dans la page web "index.html", on veut pouvoir faire quelque chose lorsque le bouton d'envoi de message est sélectionné.
Lors de votre premier TP, vous avez du utiliser un <button>
avec une capture d'évenements du click de souris.
À faire
- Mettez à jour le corps de la fonction pour poster le message du
<textarea>
à l'aide du micro-service correspondant- le texte correspondant peut être récupéré en javascript avec
$("textarea").val()
- le texte correspondant peut être récupéré en javascript avec
- Dans un deuxième temps, mettez à jour la liste des messages sur la page.
- Vous devriez maintenant avoir une page fonctionnelle, interagissant avec le micro-service de messagerie.
3.4 - Modularité du setting
Vos collègues devraient avoir les mêmes conventions, vous pouvez même utiliser votre page pour récupérer leurs messages (et eux les votres).
Vous devriez pouvoir rendre la page paramétrique sur l'adresse du micro-service, en ajoutant un champ de texte pour la stocker.
3.5 Déploiement
Afin de pouvoir rendre votre micro-service web et votre appli-web de messages disponibles en ligne, il faut un service de déploiement. J'ai essayé https://render.com/ qui est simple à mettre en oeuvre. On peut créer un service statique et/ou un service web, qui sont ce qui nous faut. Chacun est attaché à un dépot github ou gitlab.
Rendu
Je veux
- un ensemble serveur/client fonctionnel
- pour une appliweb de partage de messages
- une extension, à votre discrétion : ajout d'images, utilisateurs, etc...
- un déploiement sur par exemple http://render.com
Livrable
- Un petit rapport qui décrit ce qui a été fait
- Les liens github/gitlab des projets
- Les liens du déploiement et éventuellement des projets replit.