Menu
CoddyTech

Votre premier middleware

Fait partie de la section Les bases d’Express du Journey Node.js de Coddy. Leçon 13 sur 23.

Certaines tâches s’appliquent à chaque requête, comme écrire une ligne dans le journal, et les recopier dans chaque route n’en finirait jamais. Chaque requête a une méthode, dans req.method : GET pour récupérer quelque chose, POST pour envoyer quelque chose.

let visits = 0;

app.use((req, res, next) => {
    visits++;
    next();
});

Une fonction transmise à app.use est un middleware : Express l’exécute pour chaque requête, dans l’ordre où il a été ajouté, avant les routes qui suivent. Elle reçoit un troisième argument, next. Appeler next() transmet la requête à l’élément suivant. Un middleware qui ne répond pas et n’appelle pas next() laisse la requête en attente indéfiniment.

express.static du chapitre précédent est aussi un middleware : il répond lorsqu’il trouve un fichier et appelle next() lorsqu’il n’en trouve pas.

challenge icon

Défi

Facile

Vous voulez une ligne de journal pour chaque requête reçue par votre serveur, afin de voir ce que les visiteurs demandent.

  1. Dans server.js, juste après const app = express();, ajoutez un middleware avec app.use. Placé à cet endroit, il s’exécute avant chaque route.
  2. Pour chaque requête, il affiche une ligne dans la Console : la méthode de la requête, une espace, puis son chemin. Une requête vers /recipes/2 affiche GET /recipes/2. La méthode se trouve dans req.method (GET, POST, etc.) et le chemin dans req.url.
  3. Après l’affichage, il appelle next(), afin que la requête poursuive son chemin vers les routes.

Essayez : Appuyez sur « Jouer » et envoyez /recipes/2. Vous devriez voir Pancakes, et la Console affiche GET /recipes/2. Envoyez /api/recipes : la liste habituelle, et GET /api/recipes dans la Console. Envoyez /nope : une 404, et la Console affiche toujours GET /nope, car le middleware s’exécute avant qu’Express ne recherche une route.

Essayez vous-même

import { escapeHtml } from './html.js';
import express from 'express';
import { recipes } from './data.js';

const app = express();

app.use(express.static('public'));

app.get('/', (req, res) => {
    const items = recipes.map((r) => `<li><a href="/recipes/${r.id}">${escapeHtml(r.title)}</a></li>`);
    res.send(`<link rel="stylesheet" href="/style.css"><h1>Recipe Box</h1><ul>${items.join('')}</ul>`);
});

// type('text') envoie du texte brut, ce qui affiche chaque titre sur sa propre ligne.
app.get('/recipes', (req, res) => {
    const { tag } = req.query;
    const list = tag ? recipes.filter((recipe) => recipe.tags.includes(tag)) : recipes;
    res.type('text').send(list.map((recipe) => recipe.title).join('\n'));
});

app.get('/recipes/:id', (req, res) => {
    const recipe = recipes.find((r) => r.id === Number(req.params.id));
    if (!recipe) {
        res.status(404).send('No such recipe');
        return;
    }
    res.send(recipe.title);
});

app.get('/api/recipes', (req, res) => {
    res.json(recipes);
});

app.get('/api/recipes/:id', (req, res) => {
    const recipe = recipes.find((r) => r.id === Number(req.params.id));
    if (!recipe) {
        res.status(404).json({ error: 'No such recipe' });
        return;
    }
    res.json(recipe);
});

app.get('/about', (req, res) => {
    res.send('Recipe Box collects family recipes.');
});

app.get('/menu', (req, res) => {
    res.redirect(301, '/recipes');
});

app.get('/menu/:id', (req, res) => {
    res.redirect(301, `/recipes/${req.params.id}`);
});

app.listen(3000, () => {
    console.log('Recipe Box is running on port 3000');
});
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Les bases d’Express

Entraînez-vous par vous-même : Playground Express