Qu'est-ce que le middleware (cycle de vie de la requête) ?

Mis à jour : septembre 2026

Le middleware est une fonction du pipeline de requêtes qui inspecte ou modifie requêtes et réponses avant l’exécution de la logique de votre route. Deux sens partagent le mot — le sens « entreprise », plus ancien (brokers de messages et bus d’intégration entre applications), et le sens framework web que couvre cette entrée : des fonctions à l’intérieur d’une application, que chaque requête traverse dans l’ordre. Express énonce le modèle sans détour : une app « est essentiellement une série d’appels à des fonctions middleware » — et l’ordre de ces appels est, littéralement, le programme.

Points clés

QuestionRéponse
Le contratInspecter/modifier → puis répondre (court-circuit) ou appeler next()
La formeUn oignon : les requêtes descendent la pile, les réponses remontent
La loiOrdre d’enregistrement = ordre d’exécution — la plupart des bugs de middleware sont des bugs d’ordre
La pile canoniqueEn-têtes → CORS → parsing → logging → authn → authz → limites → routes → 404 → erreurs
vs. la passerelleLe middleware s’exécute dans une app ; une passerelle se place devant plusieurs

La pile, dans l’ordre

// JavaScript / Node.js — Express + Parse Server
// Middleware: functions the request flows through, in registration order
const app = express();
app.use(helmet());                       // 1 · security headers
app.use(cors(corsOptions));              // 2 · CORS before anything that fails
app.use(express.json({ limit: '1mb' })); // 3 · body parsing, bounded

// Parse Server IS middleware — a whole backend mounted into the stack
app.use('/parse', new ParseServer(config).app);

app.use(notFoundHandler);                // 404 — after all routes
app.use(errorHandler);                   // error handler LAST (4 args)

Chaque position a sa raison d’être : les en-têtes de sécurité en premier (ils doivent figurer sur chaque réponse, erreurs comprises) ; CORS avant tout ce qui peut échouer (sinon les navigateurs masquent la vraie erreur) ; le parsing du body, borné, avant les routes (sinon req.body vaut undefined) ; l’authentification avant l’autorisation (des permissions vérifiées pour personne sont des permissions accordées à n’importe qui) ; le rate limiting (limitation de débit) avant le travail coûteux (un limiteur placé après la requête en base ne protège rien) ; le 404 après toutes les routes ; le gestionnaire d’erreurs tout en dernier.

L’oignon, dessiné correctement

Oignon de middlewares, avec la requête qui descend et la réponse qui remonteUne requête traverse vers l'intérieur chaque couche de middleware dans l'ordre d'enregistrement jusqu'à atteindre le handler de route au cœur, puis la réponse repart vers l'extérieur à travers les mêmes couches dans l'ordre inverse, ce qui permet à chaque middleware d'agir deux fois — une fois à l'aller, une fois au retour. Une couche peut court-circuiter en envoyant une réponse avant même que les couches internes ne s'exécutent.

court-circuit :
401, aucune couche interne ne s'exécute

Requête

En-têtes / CORS

Auth

Rate limit

Handler de route
(le cœur)

Rate limit
(chemin de la réponse)

Auth
(timing, audit)

En-têtes apposés

Réponse

Une requête traverse vers l'intérieur chaque couche de middleware dans l'ordre d'enregistrement jusqu'à atteindre le handler de route au cœur, puis la réponse repart vers l'extérieur à travers les mêmes couches dans l'ordre inverse, ce qui permet à chaque middleware d'agir deux fois — une fois à l'aller, une fois au retour. Une couche peut court-circuiter en envoyant une réponse avant même que les couches internes ne s'exécutent.

La moitié que la plupart des explications omettent : le pipeline fonctionne dans les deux sens. La documentation de Django le représente comme un oignon — chaque middleware est une couche autour de la vue, au cœur — et le code situé après l’appel à next() (ou après get_response) s’exécute sur le chemin de retour de la réponse, dans l’ordre inverse. C’est là que se mesure le temps de réponse, que les en-têtes sont apposés et que le logging enregistre ce qui s’est réellement passé. Une couche qui court-circuite ne saute pas seulement le handler ; elle saute les deux moitiés de chaque couche interne — ce qui est précisément la garantie qu’une barrière d’authentification est là pour offrir.

Les bugs d’ordre qui partent en production

Le conseil générique, c’est « l’ordre compte » ; les bugs concrets sont plus instructifs. L’autorisation avant l’authentification : la vérification des permissions s’exécute contre un principal anonyme — des 401/403 intermittents, aucune exception nulle part, des heures de débogage. Le body parser après les routes : chaque handler voit req.body === undefined et accuse le client. L’auth avant CORS : le navigateur bloque la réponse 401 elle-même faute d’en-têtes CORS, si bien que le frontend voit une erreur réseau au lieu de la vraie. Les fichiers statiques avant l’auth : des fichiers privés servis de bon cœur aux utilisateurs non authentifiés. Le gestionnaire d’erreurs pas en dernier : les erreurs levées après sa position dans la pile ne l’atteignent jamais. Chacun de ces bugs passe un smoke test sur le chemin nominal — les bugs d’ordre sont de ceux qui partent en production.

Court-circuiter : quand ne pas appeler next() est le but

Le contrat a deux sorties légales : passer la main, ou terminer le cycle. Le terminer tôt n’est pas un échec du middleware — c’est la moitié de son travail : le 401 de la barrière d’auth, le 429 du limiteur, le hit de cache, la redirection, le preflight CORS traité sur-le-champ. La règle qui garde ces deux sorties honnêtes : faites toujours exactement l’une des deux — répondre, ou next(). Ne faire ni l’un ni l’autre suspend la requête indéfiniment ; faire les deux lève des erreurs headers-already-sent qui déroutent tout le monde en aval.

La même idée dans chaque framework

FrameworkLe middleware estPasser la mainAu retour
Express(req, res, next) => {}next()Le code après next() (avec précaution)
DjangoUn callable qui enveloppe get_responseget_response(request)Le code après l’appel — l’oignon
Rack / RailsUn objet avec call(env)@app.call(env)Après le retour de l’appel
Koa / Honoasync (ctx, next) => {}await next()Après le await — nativement

Un modèle, quatre accents. Le chemin d’erreur a sa propre convention dans chaque framework — dans Express, la signature à quatre arguments (err, req, res, next) est le mécanisme d’enregistrement, ce qui explique pourquoi supprimer un paramètre « inutilisé » transforme silencieusement le gestionnaire d’erreurs en middleware ordinaire qui ne se déclenche jamais.

Middleware vs. passerelles vs. hooks

MiddlewarePasserelle d’APIHooks de données
S’exécuteDans le processus d’une appDevant de nombreuses appsAutour des opérations sur les données
GranularitéPar requêtePar requête, entre servicesPar save/delete/find
MaîtriseLe pipeline de cette appRoutage, auth en bordure, limites globalesValidation, réactions aux données
Configuré parDu code, dans l’ordreLa configuration de l’infrastructureUn enregistrement par classe

Trois couches d’interception, une imbrication : la passerelle se place devant la flotte, le middleware fait passer chaque app par sa batterie de contrôles, et les hooks se déclenchent là où les requêtes deviennent des données. Une préoccupation appartient à la couche la plus externe capable de la trancher — limites de débit globales à la passerelle, auth de session dans le middleware, « cette écriture est-elle valide ? » dans le hook.

Cas d’usage courants

  • Authentification et gestion des sessions — établir l’identité une fois, tôt, pour tout ce qui suit.
  • Hygiène transversaleCORS, en-têtes de sécurité, compression, ID de requête.
  • Discipline des entrées — parsing du body avec limites de taille, contrôle du content-type, validation.
  • Observabilité — logging et mesure des temps autour de tout le pipeline, via le chemin de retour de l’oignon.
  • Protection du traficlimites de débit et barrières anti-abus qui court-circuitent avant que le coût ne soit engagé.

Dans quelle couche cela doit-il vivre ? Matrice de décision

PréoccupationCouche
S’applique à toutes les apps que vous exploitezPasserelle
S’applique à chaque requête de cette appMiddleware, positionné délibérément
S’applique à des routes précisesMiddleware au niveau du routeur
S’applique à l’écriture ou à la lecture des donnéesHooks beforeSave / beforeFind
Opérations métier sur mesureDes fonctions, pas des bricolages de pipeline
Mise en forme des erreursMiddleware d’erreurs — en dernier, quatre arguments, sans exception

Limites et trade-offs

  • L’ordre est invisible jusqu’au jour où il ne l’est plus. La pile se lit de haut en bas mais échoue d’une manière qui pointe partout ailleurs ; traitez l’enregistrement des middlewares comme du code critique, soumis à revue.
  • Chaque couche taxe chaque requête. Dix middlewares à 2 ms chacun, ce sont 20 ms sur chaque réponse ; mesurez la pile comme vous mesurez les requêtes en base.
  • L’état global est un piège. Le middleware s’exécute en concurrence sur plusieurs requêtes ; tout état mutable partagé devient une race condition — attachez les données propres à la requête à l’objet requête, et nulle part ailleurs.
  • Les pipelines masquent le flux de contrôle. Une couche qui court-circuite trois niveaux plus bas peut expliquer pourquoi une route « ne s’exécute jamais » ; le bon réflexe de débogage reste toujours le même : afficher la pile, dans l’ordre.
  • Tout ne relève pas du pipeline. La logique métier glissée en douce dans un middleware y couple chaque route ; le pipeline sert aux préoccupations transversales, pas aux préoccupations centrales.

Le middleware sur Back4app

Back4app est une plateforme open-source de Backend as a Service (BaaS) qui combine une base de données gérée, des API REST et GraphQL générées automatiquement, l’authentification, le stockage de fichiers et des fonctions serverless avec Cloud Code. La relation est ici d’une littéralité rare : le serveur de Back4app est lui-même un middleware Express — l’onglet JavaScript le montre monté avec app.use('/parse', …) dans une pile standard — et la plateforme exécute la batterie canonique pour chaque requête : en-têtes de sécurité, CORS, parsing borné, vérification des clés, authentification de session et limites de débit, dans le bon ordre, maintenus comme de l’infrastructure. Votre logique personnalisée par requête va alors là où pointe la matrice de décision plutôt que dans du code de pipeline fait main : les triggers beforeSave/beforeFind pour les règles proches des données, les Cloud Functions pour les opérations — chacun avec le contexte utilisateur de la requête attaché, ce qui représente l’essentiel de ce qu’un middleware sur mesure a toujours voulu savoir.

Questions fréquentes

Qu'est-ce qu'un middleware, en termes simples ?

Une fonction placée sur le trajet entre une requête entrante et la logique de votre route, qui traite chaque requête au passage — comme les contrôles de sécurité d'un aéroport avant la porte d'embarquement. Chacune inspecte ou modifie la requête, puis la laisse passer ou l'arrête net.

Quels sont les exemples courants de middleware ?

La pile habituelle : en-têtes de sécurité, CORS, parsing du body avec limites de taille, logging, authentification, autorisation, rate limiting, service des fichiers statiques et — tout à la fin — les handlers 404 et d'erreurs. Presque tout ce qui est transversal dans une application web est un middleware.

Comment fonctionne la chaîne de middlewares ?

Chaque fonction soit termine le cycle en envoyant une réponse, soit appelle next() pour passer la main à la suivante ; le framework parcourt la pile dans l'ordre d'enregistrement jusqu'à ce que quelque chose réponde. Le bug classique : ni répondre ni appeler next() — la requête reste suspendue indéfiniment.

L'ordre des middlewares a-t-il de l'importance ?

C'est la source de bugs numéro un. L'autorisation avant l'authentification vérifie des permissions pour personne ; un body parser placé après les routes laisse req.body à undefined ; l'auth avant CORS pousse les navigateurs à masquer la vraie erreur ; un gestionnaire d'erreurs placé ailleurs qu'en dernier n'attrape rien. L'ordre, c'est le programme.

Qu'est-ce qu'un middleware de gestion des erreurs ?

Un middleware vers lequel le framework achemine les erreurs au lieu de la chaîne normale — dans Express, reconnaissable à sa signature à quatre arguments (err, req, res, next) et enregistré en dernier. Les erreurs levées et les appels next(err) sautent tout le reste pour y atterrir, ce qui explique pourquoi sa position n'est pas négociable.

Quelle est la différence entre un middleware et un handler de route ?

L'intention et la position. Un middleware traite des préoccupations transversales pour de nombreuses routes et passe généralement la main ; le handler de route est la destination qui produit la réponse. Dans la plupart des frameworks, ce sont des fonctions structurellement identiques — le pipeline se termine simplement sur l'une d'elles.

Quelle est la différence entre un middleware et une passerelle d'API ?

La portée. Un middleware s'exécute dans le processus d'une seule application, à chaque requête ; une passerelle est une infrastructure placée devant de nombreuses applications, qui gère routage, auth et limites de débit entre services. Une passerelle est le middleware de toute votre architecture — et les deux se combinent plutôt qu'ils ne s'opposent.

Quand un middleware ne doit-il PAS appeler next() ?

Quand il a entièrement traité la requête : un refus d'auth qui renvoie 401, un rate limiter qui renvoie 429, un hit de cache, une redirection, une réponse à un preflight CORS. Court-circuiter est la fonctionnalité — la garantie que rien au-delà de la barrière ne s'exécute pour les requêtes qui ne l'ont pas franchie.

Termes associés

À comparer avec

Lectures recommandées

Prêt à construire votre backend ?

Lancez votre projet sur Back4app en quelques minutes — base de données, authentification, API et Cloud Code inclus. Sans carte bancaire.

Écrit et révisé par Back4app Engineering, Back4app Engineering · Publié le 2026-09-14