Serveur web avec express
- François Brucker
On utilise le module express pour gérer plus élégamment notre site.
Le module node express permet une gestion efficace et apaisée des site web.
Pour installer des packages node, on peut utiliser npm (node package manager) qui est livré avec node.
Tutoriel :
npm init
Comme fait précédemment on prépare le projet en créant un fichier package.json
.
- créez un dossier
serveur_express
où l'on stockera les fichiers de notre serveur. - dans cde dossier, initialisez le projet en tapant la commande :
npm init
puis en tapant entrée à chaque question pour utiliser les réponses par défaut. - ajouter la ligne
"type": "module",
dans le fichier de configurationpackage.json
, juste en-dessous de la ligne 5
A la fin de cette opération, vous devriez avoir le fichier un fichier nommé package.json
qui contient la configuration minimale d'un projet utilisant node :
{
"name": "code",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Il ne contient pour l'instant que des informations générales quant au projet. Nous allons bientôt y ajouter des modules.
Le json est un format texte pour sauvegarder des données structurée. C'est un format génial qui sert tout autant pour les fichiers de configurations que le transfert de données par le web.
Ajout d'un module
Pour cela, tapez dans un terminal placé à la racine de notre projet :
npm add --save express
N'oubliez pas --save
, sinon le module sera installé mais la dépendance ne sera pas ajoutée au fichier "package.json" ce qui est tarte.
Cette commande a ajouté une dépendance à notre fichier "package.json" :
"dependencies": {
"express": "^4.17.1"
}
A créer un fichier package-lock.json
qui contient la liste de tous les modules installés et un (gros) dossier node_modules
qui contient les modules installés.
Il y a plus de 50 modules installés alors que l'on a demandé d'installer que le module express
, car il a lui même des dépendances et ses dépendances d'autres dépendances, etc.
La différence entre package.json
et package-lock.json
est que le premier décrit les versions possibles (nous, toutes les versions ultérieures à 4.17.1) alors que package-lock.json
décrit la version effectivement installée (la 4.17.1). Cette mécanique permet de mettre à jour nos modules en supprimant le dossier node_modules
et le fichier package-lock.json
et en tapant la commande npm install
.
Sauvegarde et installation du projet
Le dossier node_modules
n'est pas un module à sauver, on peut installer toutes les dépendances avec la commande npm install
:
- grâce au fichier
package-lock.json
: la commandenpm --install
sait exactement quels modules installer - le fichier
package.json
donnant les dépendances générales de notre projet.
Routes
Le module express va nous permettre de créer nos routes (les urls que le serveur connaît) simplement.
Avant d'utiliser le module, penchons nous un peut sur que l'on veut :
- site statique : on demande à l'utilisateur de taper son prénom
- une fois que l'on appuie sur le bouton, le prénom est envoyé au server qui retourne le chiffre associé.
Pour l'instant nous n'avons qu'un site front. Donc commençons par organiser le tout.
Séparation front et back
L'usage veut que le site front soit séparé des actions du serveur. Cela permet de ne pas se mélanger les fichiers. On va donc créer un dossier serveur_web/static
et déplacer les fichier index.html
et favicon.ico
Le projet ressemble maintenant à ça, en excluant le dossier node_modules
:
.
├── index.js
└── static
└── index.html
On a utilisé la commande unix tree (tree -I node_modules
) pour réaliser le dessin ci-dessus.
Notre site en express
Modifions le fichier index.js
pour que notre site fonctionne sous express :
import path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
import express from "express";
const app = express();
const hostname = "127.0.0.1";
const port = 3000;
app.use("/static", express.static(path.join(__dirname, "/static")));
app.get("/", (req, res) => {
res.redirect(302, "/static/index.html");
});
app.use(function (req, res) {
console.log("et c'est le 404 : " + req.url);
res.statusCode = 404;
res.setHeader("Content-Type", "text/html");
res.end(
'<html><head><title>la quatre cent quatre</title></head><body><img src="https://upload.wikimedia.org/wikipedia/commons/b/b4/Peugeot_404_Champs.jpg" /></body></html>'
);
});
app.listen(port, hostname);
console.log(`Server running at http://${hostname}:${port}/`);
Tout se passe via l'objet app
, qui est le résultat de l'import de express. Chaque requête au serveur passera d'un appel de app
à l'autre (dans l'ordre du fichier).
Express appelle ces bouts de codes qui interceptent une requête un middleware
Pour chaque appel de app (dans notre cas on en a 2 app.use
et app.get
) :
- on vérifie si la requête satisfait l'appel de
app
:app.use()
: reçoit toutes les requêtesapp.get()
: ne reçoit que les requêtes de méthodeget
app.post()
: ne reçoit que les requêtes de méthodepost
- Si la requête satisfait l'appel de
app
, on vérifie si elle satisfait le 1er paramètre - Si la requête satisfait le 1er paramètre on exécute la méthode du second paramètre avec la requête en 1er paramètre.
Comme dit précédemment, la route /static
ne doit être utilisée qu'en développement. En production, on doit avoir un serveur dédié aux fichiers statiques pour éviter tout problème de charge.
Dans notre cas l'enchaînement de route est ainsi :
- 1er
app.use
: si l'url de la requête commence par/static
on envoie cette requête dans le gestionnaire de fichiers statiques de express. app.get
: si l'url de la requête est/
on redirige la requête vers/static/index.html
. Cette requête redirigée sera alors consommée par leapp.use
- 2ème
app.use
: s on arrive là, c'est que toutes les routes précédentes ont échouées : on ne peut rien faire de la requêtes on indique au client que c'est un 404. On en a aussi profité pour rendre du contenu (toute une famille).
Le dernier appel de app
doit être pour gérer les requêtes qui n'ont pas pu être consommées avant. C'est souvent que l'on ne sait pas quoi en faire donc on l'indique au client part un 404.
Pour plus d'informations sur le routage express, n'hésitez pas à consulter la documentation
Fonction next()
On peut remettre des requêtes utilisées en fonction avec la méthode next()
Ajoutez par exemple ce code en début de fichier en faisant en sorte que ce soit le 1er appel à app
:
// ...
app.use(function (req, res, next) {
let date = new Date(Date.now());
console.log(
"Time:",
date.toLocaleDateString(),
date.toLocaleTimeString(),
"; url :",
req.url
);
next(); // sans cette ligne on ne pourra pas poursuivre.
});
// ...
Notez Le format de la fonction change, remarquez qu'il y a un troisième paramètre, next
.
Lorsque vous voulez utiliser next
il faut que vous l'ajoutiez en paramètre de la fonction.
Toutes les requêtes satisfont cet appel, c'est un loggeur rudimentaire.
Si vous supprimez la ligne avec next()
plus rien ne fonctionne. Toutes les requêtes sont consommées.