Menu

Middleware Express: come funziona next(), con esempi

Un middleware di Express è una funzione (req, res, next) che viene eseguita prima del route handler. Può leggere o modificare la richiesta, chiuderla con una risposta o chiamare next() per passarla avanti.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

In Express un middleware è una funzione con la firma (req, res, next) che viene eseguita tra l'arrivo di una richiesta e l'invio della risposta. Ogni middleware può leggere o modificare req e res, chiudere la richiesta inviando una risposta, o chiamare next() per passare la richiesta alla funzione successiva. app.use(fn) aggiunge un middleware per ogni richiesta, ed Express esegue tutto nell'ordine in cui l'hai registrato.

La Console mostra i tre passaggi in ordine per ogni richiesta, e la route legge req.startedAt, una proprietà aggiunta dal logger. Invia GET /missing: i due middleware scrivono comunque il log, perché app.use() corrisponde a ogni path, poi Express risponde 404 dato che nessuna route corrisponde.

Dimenticare next()

Un middleware che non invia una risposta e non chiama next() lascia la richiesta appesa. Il client aspetta fino al timeout e nei log non compare niente, per questo è un bug comune con i middleware. Cancella next(); dal logger qui sopra e invia di nuovo GET /: la richiesta non riceve mai risposta.

La regola è semplice: ogni percorso dentro un middleware finisce con esattamente una di queste cose:

Anche chiamare next() dopo aver inviato una risposta è un bug. L'handler successivo prova a inviare una seconda risposta ed Express lancia ERR_HTTP_HEADERS_SENT. Scrivi return res.status(401).json(...) così la funzione si ferma lì.

Un controllo di accesso che ferma la richiesta

Un middleware che rifiuta una richiesta invia la risposta da solo e non chiama mai next(). Passalo come argomento in più a una route per proteggere solo quella:

La prima richiesta riceve 401 con {"error":"Missing or wrong API key"}. Aggiungi l'header x-api-key: secret123 nella barra della richiesta e inviala di nuovo: ora la risposta è {"users":42,"caller":"reporting-app"}. /public non esegue mai il controllo.

Dove viene eseguito un middleware

ScriviViene eseguito per
app.use(fn)Ogni richiesta, ogni metodo
app.use('/api', fn)I path che iniziano con /api
app.get('/admin', fn, handler)Solo GET /admin, prima di handler
router.use(fn)Ogni route di quel router

L'ordine fa parte del significato. Un logger registrato dopo le route non scrive mai le richieste a cui quelle route hanno risposto, perché una route che invia una risposta non chiama next(). Registra prima i middleware globali come logging, parsing del body e CORS, poi le route, poi gli handler 404 e degli errori.

I middleware integrati

Express include alcuni middleware da aggiungere con app.use(). I body parser riempiono req.body; senza di loro è undefined.

MiddlewareCosa fa
express.json()Fa il parsing dei body JSON (Content-Type: application/json)
express.urlencoded()Fa il parsing dei form HTML inviati (name=Ada&age=36)
express.text()Mette un body di testo semplice in req.body come stringa
express.static('public')Serve i file di una cartella

Invia POST /echo con il body {"name": "Ada"} e la risposta contiene "body":{"name":"Ada"}. Togli la riga express.json(), inviala di nuovo, e body sparisce dalla risposta: req.body è undefined e JSON.stringify omette i valori undefined. Anche pacchetti come cors, helmet e morgan sono middleware: li installi con npm install e li passi ad app.use() nello stesso modo. La pagina su express.static spiega come servire file.

Errori comuni

Chiamare il middleware invece di passarlo. app.use(logger()) esegue logger una volta all'avvio e registra il suo valore di ritorno. Scrivi app.use(logger). (express.json() ha le parentesi perché restituisce una funzione middleware.)

Aggiungere il body parser dopo le route. Le route girano per prime e vedono req.body come undefined.

Aspettarsi che app.use('/admin', fn) corrisponda a un solo path. Viene eseguito anche per /admin/users e per ogni altro path sotto /admin, con ogni metodo. Per proteggere una sola route, passa il middleware ad app.get('/admin', fn, handler).

Domande frequenti

Che differenza c'è tra un middleware e un route handler?

Tecnicamente nessuna: sono entrambi funzioni (req, res, next). Per convenzione un route handler chiude la richiesta con una risposta, mentre un middleware di solito fa un lavoro condiviso e chiama next().

Un middleware può essere async?

Sì. In Express 5 un middleware async che lancia un errore o restituisce una promise rifiutata manda l'errore all'error handler in automatico. Fai await di quello che ti serve, poi chiama next().

Cosa fa next('route')?

Salta gli handler rimanenti della route corrente e passa alla route successiva che corrisponde. Funziona solo negli handler aggiunti con app.get(), app.post() e le altre funzioni dei metodi, non in app.use().

Come salto un middleware per una sola route?

Registra quella route prima del middleware, così risponde per prima, oppure controlla il path dentro il middleware (if (req.path === '/health') return next();). Applicare il middleware per router o per route invece che a tutta l'app spesso elimina il problema.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

Inizia