Scrivere middleware da usare nelle applicazioni Express

Panoramica

Le funzioni middleware sono funzioni che hanno accesso all’oggetto richiesta (req), l’oggetto risposta (res), e la funzione next nel ciclo richiesta-risposta dell’applicazione. La funzione next è una funzione nel router Express che, quando invocata, esegue il middleware successivo al middleware corrente.

Le funzioni middleware possono eseguire i seguenti compiti:

  • Eseguire qualsiasi codice.
  • Apportare modifiche agli oggetti richiesta e risposta.
  • Finire il ciclo richiesta-risposta.
  • Chiamare il prossimo middleware nello stack.

Se la funzione middleware corrente non termina il ciclo richiesta-risposta, deve chiamare next() per passare il controllo alla funzione middleware successiva. Altrimenti, la richiesta verrà lasciata in sospeso.

La figura seguente mostra gli elementi di una chiamata di funzione middleware:

MetodoHTTP per il quale la funzione middleware si applica.
Percorso (route) per il quale si applica la funzione middleware.
La funzione middleware.
Orgomento di callback alla funzione middleware, chiamato “next” per convenzione.
argomento di rispostaHTTP alla funzione middleware, chiamato “res” per convenzione.
argomento di richiestaHTTP alla funzione middleware, chiamato “req” per convenzione.

A partire da Express 5, le funzioni middleware che restituiscono una Promise chiameranno next(value) quando rifiutano o lanciano un errore. next sarà chiamato con il valore rifiutato o l’errore lanciato.

Esempio

Ecco un esempio di una semplice applicazione Express “Hello World”.Il resto di questo articolo definirà e aggiungerà tre funzioni middleware all’applicazione: una chiamata myLogger che stampa un semplice messaggio di log, una chiamata requestTime che visualizza il timestamp della richiesta HTTP, e una chiamata validateCookies che valida i cookie in entrata.

var express = require('express')var app = express()app.get('/', function (req, res) { res.send('Hello World!')})app.listen(3000)

Funzione middleware myLogger

Ecco un semplice esempio di una funzione middleware chiamata “myLogger”. Questa funzione stampa semplicemente “LOGGED” quando una richiesta all’app passa attraverso di essa. La funzione middleware è assegnata ad una variabile chiamata myLogger.

var myLogger = function (req, res, next) { console.log('LOGGED') next()}

Nota la chiamata sopra a next(). La funzione next() non fa parte delle API di Node.js o Express, ma è il terzo argomento che viene passato alla funzione middleware. La funzione next() potrebbe avere qualsiasi nome, ma per convenzione si chiama sempre “next”.

Per caricare la funzione middleware, chiamare app.use(), specificando la funzione middleware.Per esempio, il seguente codice carica la funzione middleware myLogger prima del percorso verso la root (/).

var express = require('express')var app = express()var myLogger = function (req, res, next) { console.log('LOGGED') next()}app.use(myLogger)app.get('/', function (req, res) { res.send('Hello World!')})app.listen(3000)

Ogni volta che l’applicazione riceve una richiesta, stampa il messaggio “LOGGED” sul terminale.

L’ordine di caricamento del middleware è importante: le funzioni middleware caricate per prime vengono anche eseguite per prime.

Se myLogger viene caricato dopo il percorso del percorso root, la richiesta non lo raggiunge mai e l’app non stampa “LOGGED”, perché il gestore del percorso root termina il ciclo richiesta-risposta.

La funzione middleware myLogger stampa semplicemente un messaggio, poi passa la richiesta alla prossima funzione middleware nello stack chiamando la funzione next().

Funzione middleware requestTime

In seguito, creeremo una funzione middleware chiamata “requestTime” e aggiungeremo una proprietà chiamata requestTime all’oggetto richiesta.

var requestTime = function (req, res, next) { req.requestTime = Date.now() next()}

L’applicazione ora usa la funzione middleware requestTime. Inoltre, la funzione di callback del percorso della root usa la proprietà che la funzione middleware aggiunge a req (l’oggetto della richiesta).

var express = require('express')var app = express()var requestTime = function (req, res, next) { req.requestTime = Date.now() next()}app.use(requestTime)app.get('/', function (req, res) { var responseText = 'Hello World!<br>' responseText += '<small>Requested at: ' + req.requestTime + '</small>' res.send(responseText)})app.listen(3000)

Quando fate una richiesta alla root dell’app, l’app ora visualizza il timestamp della vostra richiesta nel browser.

Funzione middleware validateCookies

Infine, creeremo una funzione middleware che convalida i cookie in arrivo e invia una risposta 400 se i cookie non sono validi.

Ecco un esempio di funzione che convalida i cookie con un servizio asincrono esterno.

async function cookieValidator (cookies) { try { await externallyValidateCookie(cookies.testCookie) } catch { throw new Error('Invalid cookies') }}

Qui usiamo il middleware cookie-parser per analizzare i cookie in arrivo dall’oggetto req e passarli alla nostra funzione cookieValidator. Il validateCookies middleware restituisce una Promessa che al rifiuto farà scattare automaticamente il nostro gestore di errori.

var express = require('express')var cookieParser = require('cookie-parser')var cookieValidator = require('./cookieValidator')var app = express()async function validateCookies (req, res, next) { await cookieValidator(req.cookies) next()}app.use(cookieParser())app.use(validateCookies)// error handlerapp.use(function (err, req, res, next) { res.status(400).send(err.message)})app.listen(3000)

Nota come next() viene chiamato dopo await cookieValidator(req.cookies). Questo assicura che se cookieValidator si risolve, il prossimo middleware nello stack verrà chiamato. Se si passa qualcosa alla funzione next() (tranne la stringa 'route' o 'router'), Express considera la richiesta corrente come un errore e salta qualsiasi altra funzione di routing e middleware che non gestisca gli errori.

Perché si ha accesso all’oggetto richiesta, all’oggetto risposta, alla prossima funzione middleware nello stack e all’intera API di Node.js, le possibilità con le funzioni middleware sono infinite.

Per maggiori informazioni sul middleware Express, vedere: Usare il middleware Express.

Middleware configurabile

Se hai bisogno che il tuo middleware sia configurabile, esporta una funzione che accetta un oggetto opzioni o altri parametri, che, poi, restituisce l’implementazione del middleware basata sui parametri di input.

File: my-middleware.js

module.exports = function (options) { return function (req, res, next) { // Implement the middleware function based on the options object next() }}

Il middleware può ora essere usato come mostrato qui sotto.

var mw = require('./my-middleware.js')app.use(mw({ option1: '1', option2: '2' }))

Riferimento a cookie-session e compression per esempi di middleware configurabile.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *