Schreiben von Middleware zur Verwendung in Express-Apps

Übersicht

Middleware-Funktionen sind Funktionen, die Zugriff auf das Request-Objekt (req) haben, das Response-Objekt (res) und die next-Funktion im Anfrage-Antwort-Zyklus der Anwendung. Die next-Funktion ist eine Funktion im Express-Router, die, wenn sie aufgerufen wird, die auf die aktuelle Middleware folgende Middleware ausführt.

Middleware-Funktionen können folgende Aufgaben ausführen:

  • Beliebigen Code ausführen.
  • Änderungen an den Request- und Response-Objekten vornehmen.
  • Den Request-Response-Zyklus beenden.
  • Die nächste Middleware im Stack aufrufen.

Wenn die aktuelle Middleware-Funktion den Request-Response-Zyklus nicht beendet, muss sie next() aufrufen, um die Kontrolle an die nächste Middleware-Funktion zu übergeben. Andernfalls bleibt die Anfrage hängen.

Die folgende Abbildung zeigt die Elemente eines Middleware-Funktionsaufrufs:

HTTP-Methode, für die die Middleware-Funktion gilt.
Pfad (Route), für den die Middleware-Funktion gilt.
Die Middleware-Funktion.
Callback-Argument zur Middleware-Funktion, per Konvention „next“ genannt.
HTTP-Antwort-Argument an die Middleware-Funktion, per Konvention „res“ genannt.
HTTP-Anfrage-Argument an die Middleware-Funktion, per Konvention „req“ genannt.

Beginnend mit Express 5 rufen Middleware-Funktionen, die ein Promise zurückgeben, next(value) auf, wenn sie ablehnen oder einen Fehler auslösen. next wird entweder mit dem abgelehnten Wert oder dem geworfenen Fehler aufgerufen.

Beispiel

Hier ist ein Beispiel für eine einfache „Hello World“ Express Anwendung.Im weiteren Verlauf dieses Artikels werden drei Middleware-Funktionen definiert und der Anwendung hinzugefügt: eine mit dem Namen myLogger, die eine einfache Protokollmeldung ausgibt, eine mit dem Namen requestTime, die den Zeitstempel der HTTP-Anfrage anzeigt, und eine mit dem Namen validateCookies, die eingehende Cookies validiert.

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

Middleware-Funktion myLogger

Hier ist ein einfaches Beispiel für eine Middleware-Funktion namens „myLogger“. Diese Funktion gibt einfach „LOGGED“ aus, wenn eine Anfrage an die App sie durchläuft. Die Middleware-Funktion wird einer Variablen mit dem Namen myLogger zugewiesen.

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

Beachten Sie den Aufruf oben zu next(). Das next() ist nicht Teil der Node.js- oder Express-API, sondern ist das dritte Argument, das an die Middleware-Funktion übergeben wird. Die next()-Funktion könnte beliebig benannt werden, aber per Konvention wird sie immer „next“ genannt.

Um die Middleware-Funktion zu laden, rufen Sie app.use() auf und geben dabei die Middleware-Funktion an.Der folgende Code lädt zum Beispiel die myLogger Middleware-Funktion vor der Route zum Root-Pfad (/).

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)

Jedes Mal, wenn die App eine Anfrage erhält, gibt sie die Meldung „LOGGED“ auf dem Terminal aus.

Die Reihenfolge des Ladens der Middleware ist wichtig: Middleware-Funktionen, die zuerst geladen werden, werden auch zuerst ausgeführt.

Wenn myLogger nach der Route zum Root-Pfad geladen wird, erreicht die Anfrage diesen nie und die App gibt nicht „LOGGED“ aus, da der Route-Handler des Root-Pfads den Anfrage-Antwort-Zyklus beendet.

Die Middleware-Funktion myLogger druckt einfach eine Meldung aus und gibt dann die Anfrage an die nächste Middleware-Funktion im Stapel weiter, indem sie die next()-Funktion aufruft.

Middleware-Funktion requestTime

Als Nächstes erstellen wir eine Middleware-Funktion namens „requestTime“ und fügen dem request-Objekt eine Eigenschaft namens requestTime hinzu.

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

Die App verwendet nun die requestTime Middleware-Funktion. Außerdem verwendet die Callback-Funktion der Root-Pfad-Route die Eigenschaft, die die Middleware-Funktion zu req (dem Anfrageobjekt) hinzufügt.

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)

Wenn Sie eine Anfrage an die Root der App stellen, zeigt die App jetzt den Zeitstempel Ihrer Anfrage im Browser an.

Middleware-Funktion validateCookies

Zuletzt erstellen wir eine Middleware-Funktion, die eingehende Cookies validiert und eine 400-Antwort sendet, wenn Cookies ungültig sind.

Hier ist eine Beispielfunktion, die Cookies mit einem externen asynchronen Dienst validiert.

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

Hier verwenden wir die cookie-parser-Middleware, um eingehende Cookies aus dem req-Objekt zu parsen und sie an unsere cookieValidator-Funktion zu übergeben. Die validateCookies Middleware gibt ein Promise zurück, das bei Ablehnung automatisch unseren Error-Handler auslöst.

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)

Beachten Sie, wie next() nach await cookieValidator(req.cookies) aufgerufen wird. Dies stellt sicher, dass wenn cookieValidator aufgelöst wird, die nächste Middleware im Stack aufgerufen wird. Wenn Sie der Funktion next() irgendetwas übergeben (außer der Zeichenkette 'route' oder 'router'), betrachtet Express die aktuelle Anfrage als Fehler und überspringt alle verbleibenden Routing- und Middleware-Funktionen, die keine Fehler behandeln.

Da Sie Zugriff auf das Request-Objekt, das Response-Objekt, die nächste Middleware-Funktion im Stack und die gesamte Node.js-API haben, sind die Möglichkeiten mit Middleware-Funktionen endlos.

Weitere Informationen über Express-Middleware finden Sie unter: Express-Middleware verwenden.

Konfigurierbare Middleware

Wenn Ihre Middleware konfigurierbar sein soll, exportieren Sie eine Funktion, die ein Options-Objekt oder andere Parameter akzeptiert und dann die Middleware-Implementierung basierend auf den Eingabeparametern zurückgibt.

Datei: my-middleware.js

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

Die Middleware kann nun wie unten gezeigt verwendet werden.

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

Beispiele für konfigurierbare Middleware finden Sie unter cookie-session und compression.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.