Schrijven van middleware voor gebruik in Express apps

Overzicht

Middleware functies zijn functies die toegang hebben tot het request object (req), het response object (res), en de next functie in de request-response cyclus van de applicatie. De next functie is een functie in de Express router die, wanneer deze wordt aangeroepen, de middleware uitvoert die de huidige middleware opvolgt.

Middleware functies kunnen de volgende taken uitvoeren:

  • Uitvoeren van willekeurige code.
  • Veranderingen aanbrengen in het request en de response objecten.
  • De request-response-cyclus beëindigen.
  • De volgende middleware in de stack oproepen.

Als de huidige middleware-functie de request-response-cyclus niet beëindigt, moet hij next() oproepen om de controle door te geven aan de volgende middleware-functie. Anders blijft het verzoek hangen.

De volgende figuur toont de elementen van een aanroep van een middleware-functie:

HTTP-methode waarvoor de middleware-functie geldt.

Path (route) waarvoor de middleware-functie geldt.
De middleware-functie.
Callback-argument voor de middleware-functie, die volgens afspraak “next” wordt genoemd.
HTTP response argument voor de middleware functie, bij conventie “res” genoemd.
HTTP request argument voor de middleware functie, bij conventie “req” genoemd.

Met ingang van Express 5 zullen middlewarefuncties die een belofte retourneren next(value) aanroepen wanneer ze een fout afwijzen of een foutmelding geven. next wordt aangeroepen met ofwel de afgekeurde waarde ofwel de gegooide Error.

Example

Hier volgt een voorbeeld van een eenvoudige “Hello World” Express applicatie.De rest van dit artikel zal drie middleware functies definiëren en toevoegen aan de applicatie: een genaamd myLogger die een eenvoudig log bericht afdrukt, een genaamd requestTime die de timestamp van het HTTP verzoek weergeeft, en een genaamd validateCookies die de inkomende cookies valideert.

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

Middleware functie mijnLogger

Hier is een eenvoudig voorbeeld van een middleware functie genaamd “mijnLogger”. Deze functie drukt gewoon “LOGGED” af wanneer een verzoek aan de app erdoorheen gaat. De middleware-functie wordt toegewezen aan een variabele met de naam myLogger.

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

Let op de oproep hierboven aan next(). Het aanroepen van deze functie roept de volgende middleware functie in de app op.De next() functie is geen onderdeel van de Node.js of Express API, maar is het derde argument dat wordt doorgegeven aan de middleware functie. De next() functie kan van alles heten, maar wordt volgens afspraak altijd “next” genoemd.Om verwarring te voorkomen, moet deze conventie altijd worden gebruikt.

Om de middleware functie te laden, roept u app.use() op, met vermelding van de middleware functie.De volgende code laadt bijvoorbeeld de myLogger middleware-functie vóór de route naar het root-pad (/).

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)

elke keer dat de app een verzoek ontvangt, drukt hij het bericht “LOGGED” af op de terminal.

De volgorde van het laden van middleware is belangrijk: middleware-functies die eerst worden geladen, worden ook eerst uitgevoerd.

Als myLogger na de route naar het rootpad wordt geladen, bereikt het verzoek het nooit en drukt de app geen “LOGGED” af, omdat de routehandler van het rootpad de request-response-cyclus beëindigt.

De middleware functie myLogger drukt gewoon een bericht af, en geeft dan het verzoek door aan de volgende middleware functie in de stack door de next() functie aan te roepen.

Middleware functie requestTime

Volgende, we maken een middleware functie genaamd “requestTime” en voegen een eigenschap genaamd requestTime toe aan het request object.

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

De app gebruikt nu de requestTime middleware functie. Ook gebruikt de callback functie van de root path route de eigenschap die de middleware functie toevoegt aan req (het request object).

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)

Wanneer u een request doet naar de root van de app, geeft de app nu de timestamp van uw request weer in de browser.

Middleware-functie validateCookies

Tot slot maken we een middleware-functie die inkomende cookies valideert en een 400-respons stuurt als de cookies ongeldig zijn.

Hier volgt een voorbeeldfunctie die cookies valideert met een externe async service.

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

Hier gebruiken we de cookie-parser middleware om inkomende cookies van het req object te ontleden en aan onze cookieValidator functie door te geven. De validateCookies middleware retourneert een Promise die bij afwijzing automatisch onze error handler activeert.

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)

Merk op dat next() wordt aangeroepen na await cookieValidator(req.cookies). Dit zorgt ervoor dat als cookieValidator wordt opgelost, de volgende middleware in de stack wordt aangeroepen. Als u iets doorgeeft aan de next() functie (behalve de string 'route' of 'router'), beschouwt Express het huidige verzoek als een fout en zal het alle overige niet-fout afhandelende routing en middleware functies overslaan.

Omdat je toegang hebt tot het request object, het response object, de volgende middleware functie in de stack, en de hele Node.js API, zijn de mogelijkheden met middleware functies eindeloos.

Voor meer informatie over Express middleware, zie: Express middleware gebruiken.

Configureerbare middleware

Als u wilt dat uw middleware configureerbaar is, exporteer dan een functie die een optie-object of andere parameters accepteert, die vervolgens de middleware-implementatie retourneert op basis van de invoerparameters.

Bestand: my-middleware.js

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

De middleware kan nu worden gebruikt zoals hieronder wordt getoond.

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

Refereer naar cookie-session en compressie voor voorbeelden van configureerbare middleware.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *