Aller au contenu

Express : middlewares

Un middleware est une fonction (req, res, next) qui s’exécute entre la réception de la requête et la réponse. Les middlewares forment une chaîne ; chacun appelle next() pour passer au suivant, ou répond lui-même.

function journal(req, res, next) {
const debut = Date.now();
res.on('finish', () => {
console.log(
`${req.method} ${req.originalUrl} ${res.statusCode} ${Date.now() - debut} ms`,
);
});
next();
}
app.use(journal);

Un middleware doit soit appeler next(), soit envoyer une réponse : sinon la requête reste en attente.

app.use(journal); // toutes les routes
app.use('/api', verifierJeton); // routes sous /api
app.get('/admin', verifierJeton, (req, res) => res.send('admin')); // une route
routeur.use(limiter); // toutes les routes d'un routeur

L’ordre de déclaration compte : un middleware s’applique aux routes déclarées après lui.

app.use(express.json({ limit: '100kb' }));
app.use(express.urlencoded({ extended: false }));
app.use(express.static('public', { maxAge: '1d' }));
app.use(express.text()); // text/plain
app.use(express.raw()); // corps binaire

Limiter la taille des corps (limit) protège contre l’envoi de requêtes volumineuses.

Fenêtre de terminal
npm install morgan compression cors cookie-parser
import morgan from 'morgan';
import compression from 'compression';
import cors from 'cors';
import cookieParser from 'cookie-parser';
app.use(morgan('combined')); // journal d'accès
app.use(compression()); // compression des réponses
app.use(cors({ origin: 'https://exemple.com' }));
app.use(cookieParser());
Paquet Rôle
morgan Journal des requêtes HTTP
compression Compression gzip/deflate (souvent faite par le reverse proxy : éviter le doublon)
cors En-têtes CORS (appels depuis un autre domaine)
cookie-parser Lecture des cookies
helmet En-têtes de sécurité (voir Sécurité et production)
express-rate-limit Limitation du nombre de requêtes
multer Envoi de fichiers (voir Fichiers statiques, envois et vues)
function verifierJeton(req, res, next) {
const entete = req.get('Authorization') ?? '';
const [type, jeton] = entete.split(' ');
if (type !== 'Bearer' || jeton !== process.env.API_JETON) {
return res.status(401).json({ erreur: 'non authentifié' });
}
next();
}
app.use('/api', verifierJeton);

Pour une application réelle, vérifier un jeton signé (JWT) ou une session plutôt qu’une valeur fixe, et comparer les secrets en temps constant (crypto.timingSafeEqual).

app.use((req, res, next) => {
res.locals.demarreA = Date.now();
req.utilisateur = { id: 1, role: 'admin' };
next();
});
app.get('/moi', (req, res) => res.json(req.utilisateur));

res.locals sert aussi à passer des données aux vues.

app.use(async (req, res, next) => {
req.utilisateur = await chargerUtilisateur(req.get('X-Id'));
next();
});

En Express 5, une erreur levée (ou une promesse rejetée) dans un middleware ou un gestionnaire asynchrone est transmise automatiquement au gestionnaire d’erreurs. Avec Express 4, il fallait attraper l’erreur et appeler next(err).

Un gestionnaire d’erreurs a quatre paramètres et se déclare en dernier :

app.use((req, res) => {
res.status(404).json({ erreur: 'introuvable' });
});
app.use((err, req, res, next) => {
console.error(err);
if (res.headersSent) return next(err);
const statut = err.statut ?? 500;
res.status(statut).json({
erreur: statut === 500 ? 'erreur interne' : err.message,
});
});

Ne pas renvoyer err.stack ni le message d’une erreur interne au client : ils révèlent le fonctionnement du serveur.

Erreur volontaire avec un code :

class ErreurHttp extends Error {
constructor(statut, message) {
super(message);
this.statut = statut;
}
}
app.get('/clients/:id', async (req, res) => {
const client = await trouverClient(Number(req.params.id));
if (!client) throw new ErreurHttp(404, 'client introuvable');
res.json(client);
});
Symptôme Piste
La requête ne se termine jamais Middleware sans next() ni réponse
Le middleware n’agit pas sur une route Déclaré après la route
Cannot set headers after they are sent Réponse envoyée puis next() : utiliser return
Le gestionnaire d’erreurs n’est pas appelé Moins de quatre paramètres : (err, req, res, next)
Erreur CORS dans le navigateur origin non autorisé, ou requête préliminaire (OPTIONS) mal traitée
Corps tronqué ou PayloadTooLargeError Limite limit dépassée

Ubuntu 24.04 et 26.04 : différences à connaître

Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »

Aucune : les middlewares dépendent d’Express et de Node.js, pas de la distribution.