Middleware in Express ist eine Funktion mit der Signatur (req, res, next), die zwischen dem Eintreffen einer Anfrage und dem Senden der Antwort läuft. Jede Middleware kann req und res lesen oder ändern, die Anfrage mit einer Antwort beenden oder mit next() an die nächste Funktion in der Reihe weitergeben. app.use(fn) fügt Middleware für jede Anfrage hinzu, und Express führt alles in der Reihenfolge aus, in der du es registriert hast.
Die Console gibt bei jeder Anfrage die drei Schritte der Reihe nach aus, und die Route liest req.startedAt, eine Eigenschaft, die der Logger hinzugefügt hat. Sende GET /missing: Die beiden Middleware-Funktionen loggen trotzdem, weil app.use() auf jeden Pfad passt, und danach antwortet Express mit 404, weil keine Route gepasst hat.
next() vergessen
Eine Middleware, die weder eine Antwort sendet noch next() aufruft, lässt die Anfrage hängen. Der Client wartet bis zum Timeout, und in den Logs erscheint nichts, was das zu einem häufigen Middleware-Bug macht. Lösch next(); aus logger oben und sende noch einmal GET /: Die Anfrage bekommt nie eine Antwort.
Die Regel ist einfach: Jeder Weg durch eine Middleware endet in genau einem davon:
next(), um weiterzumachen,next(err), um zum Error Handler zu springen (siehe Express Error Handling),- einer Antwort wie
res.json()oderres.status(401).send().
next() nach dem Senden einer Antwort aufzurufen, ist ebenfalls ein Bug. Der nächste Handler versucht, eine zweite Antwort zu senden, und Express wirft ERR_HTTP_HEADERS_SENT. Schreib return res.status(401).json(...), damit die Funktion dort aufhört.
Eine Auth-Prüfung, die die Anfrage stoppt
Middleware, die eine Anfrage ablehnt, sendet die Antwort selbst und ruft nie next() auf. Übergib sie einer Route als zusätzliches Argument, um nur diese Route zu schützen:
Die erste Anfrage bekommt 401 mit {"error":"Missing or wrong API key"}. Füg in der Request-Leiste den Header x-api-key: secret123 hinzu und sende sie noch einmal: Jetzt lautet die Antwort {"users":42,"caller":"reporting-app"}. /public führt die Prüfung nie aus.
Wo Middleware läuft
| Du schreibst | Läuft für |
|---|---|
app.use(fn) | Jede Anfrage, jede Methode |
app.use('/api', fn) | Pfade, die mit /api beginnen |
app.get('/admin', fn, handler) | Nur GET /admin, vor handler |
router.use(fn) | Jede Route dieses Routers |
Die Reihenfolge gehört zur Bedeutung. Ein Logger, der nach den Routen registriert wird, loggt nie Anfragen, die diese Routen beantwortet haben, weil eine Route, die eine Antwort sendet, next() nicht aufruft. Registrier Middleware für die ganze App, etwa Logging, Body-Parsing und CORS, zuerst, dann die Routen, dann den 404- und den Error Handler.
Eingebaute Middleware
Express bringt ein paar Middleware-Funktionen mit, die du mit app.use() hinzufügst. Die Body-Parser füllen req.body; ohne sie ist es undefined.
| Middleware | Was sie macht |
|---|---|
express.json() | Parst JSON-Bodys (Content-Type: application/json) |
express.urlencoded() | Parst HTML-Formulare (name=Ada&age=36) |
express.text() | Legt einen Text-Body als String in req.body |
express.static('public') | Liefert Dateien aus einem Ordner aus |
Sende POST /echo mit dem Body {"name": "Ada"}, und die Antwort enthält "body":{"name":"Ada"}. Entferne die Zeile express.json(), sende noch einmal, und body fehlt in der Antwort: req.body ist undefined, und JSON.stringify lässt undefinierte Werte weg. Pakete wie cors, helmet und morgan sind ebenfalls Middleware: Du installierst sie mit npm install und übergibst sie genauso an app.use(). Die Seite zu express.static behandelt das Ausliefern von Dateien.
Häufige Fehler
Die Middleware aufrufen, statt sie zu übergeben. app.use(logger()) führt logger einmal beim Start aus und registriert den Rückgabewert. Schreib app.use(logger). (express.json() hat Klammern, weil es eine Middleware-Funktion zurückgibt.)
Den Body-Parser nach den Routen hinzufügen. Die Routen laufen zuerst und sehen req.body als undefined.
Erwarten, dass app.use('/admin', fn) auf einen einzigen Pfad passt. Es läuft auch für /admin/users und jeden anderen Pfad unter /admin, für jede Methode. Um eine einzelne Route zu schützen, übergib die Middleware an app.get('/admin', fn, handler).
Häufig gestellte Fragen
Was ist der Unterschied zwischen Middleware und einem Route-Handler?
Technisch keiner: Beides sind Funktionen mit (req, res, next). Per Konvention beendet ein Route-Handler die Anfrage mit einer Antwort, während Middleware meist eine gemeinsame Aufgabe erledigt und next() aufruft.
Kann Middleware async sein?
Ja. In Express 5 schickt eine async-Middleware, die wirft oder ein abgelehntes Promise zurückgibt, den Fehler automatisch an deinen Error Handler. Warte mit await auf das, was du brauchst, und ruf dann next() auf.
Was macht next('route')?
Es überspringt die restlichen Handler der aktuellen Route und geht zur nächsten passenden Route. Das funktioniert nur in Handlern, die mit app.get(), app.post() und den anderen Methodenfunktionen hinzugefügt wurden, nicht in app.use().
Wie überspringe ich eine Middleware für eine Route?
Registrier diese Route vor der Middleware, damit sie zuerst antwortet, oder prüf den Pfad in der Middleware (if (req.path === '/health') return next();). Oft hilft es schon, die Middleware pro Router oder pro Route statt für die ganze App einzubinden.