Menu

Express Router und Routing: Routen, Parameter, Präfixe

Eine Route in Express ist eine Methode, ein Pfad und ein Handler: app.get('/users/:id', handler). Fass zusammengehörige Routen in einem express.Router() zusammen und häng ihn mit app.use('/api', router) unter einem Präfix ein.

Diese Seite enthält ausführbare Editoren. Bearbeiten, ausführen und Ausgabe sofort sehen.

Routing in Express ordnet einer HTTP-Methode und einem Pfad eine Handler-Funktion zu: app.get('/users', handler) beantwortet GET-Anfragen an /users, und app.post(), app.put() und app.delete() machen dasselbe für die anderen Methoden. Ein Segment, das mit einem Doppelpunkt beginnt, wie in /users/:id, ist ein Routenparameter, dessen Wert in req.params landet. Damit eine wachsende App übersichtlich bleibt, packst du zusammengehörige Routen in einen express.Router() und hängst ihn mit app.use('/api', router) unter einem Präfix ein.

GET /users/2 antwortet mit {"id":2,"name":"Linus"}. Routenparameter sind immer Strings, deshalb vergleicht der Handler mit Number(req.params.id). Sende POST /users mit dem Body {"name": "Grace"}, um 201 zu bekommen, dann DELETE /users/1 und GET /users, um zu sehen, wie sich die Liste ändert.

express.Router() mit Präfix

Ein Router ist eine Mini-App mit eigenen Routen und eigener Middleware. Seine Pfade sind relativ: Eine Route /:id in einem Router, der unter /api/books eingehängt ist, beantwortet /api/books/:id. In einem echten Projekt steht jeder Router in einer eigenen Datei und endet mit module.exports = router.

GET /api/books/1 liefert {"id":1,"title":"Dune"}. router.route('/:id') schreibt den Pfad einmal und hängt pro Methode einen Handler an; sende PUT /api/books/1, und du bekommst {"updated":"1"}. Ändere den Einhängepfad in /v2/books, und derselbe Router antwortet stattdessen dort.

Reihenfolge der Routen: Der erste Treffer gewinnt

Express probiert Routen in der Reihenfolge, in der du sie registrierst, und hört bei der ersten auf, die eine Antwort sendet. Eine Parameter-Route fängt alles an ihrer Position ab, ein fester Pfad, der danach registriert wird, wird also nie erreicht:

GET /users/new antwortet mit {"route":"/users/:id","id":"new"}: Die Parameter-Route wurde zuerst registriert und hat die Anfrage übernommen. Schieb die Route /users/new über /users/:id und führ es noch einmal aus, um {"route":"/users/new"} zu bekommen. Sende dann GET /books, um den 404-Handler ganz unten zu erreichen.

Der 404-Handler

Express beantwortet eine Anfrage ohne passende Route mit seiner eigenen HTML-Seite, Cannot GET /books. Für eine API willst du meist JSON, also füg wie im Block oben ein app.use() ohne Pfad als allerletzte Route hinzu. Es läuft nur, wenn jede Route davor die Anfrage weitergereicht hat. Fehler, die Handler werfen, sind ein anderer Fall mit einem eigenen Handler mit vier Argumenten, beschrieben unter Express Error Handling.

Routenpfade in Express 5

Express 5 hat die Pfadsyntax geändert, und die meisten Snippets im Netz sind für Express 4 geschrieben:

MusterExpress 4Express 5
Beliebiger Pfadapp.get('*', fn)app.get('/*splat', fn)
Optionaler Parameter/users/:id?/users{/:id}
Muster für einen Parameter/users/:id(\\d+)Nicht unterstützt; prüf den Wert im Handler

Ein einzelnes * oder ein ? nach einem Parameter wirft beim Registrieren der Route einen TypeError, die App startet also nicht.

Häufige Fehler

Den 404-Handler zuerst registrieren. app.use() ohne Pfad passt auf alles, also bekommt jede Anfrage die 404. Lass ihn ganz unten.

Vergessen, dass das Präfix entfernt wird. In einem Router, der unter /api eingehängt ist, enthält req.path kein /api. Nimm req.originalUrl, wenn du den vollständigen Pfad brauchst.

Einen Parameter mit einer Zahl vergleichen. req.params.id === 1 ist immer false, weil req.params.id der String '1' ist.

Häufig gestellte Fragen

Was ist der Unterschied zwischen app.use und app.get?

app.get('/users', fn) führt fn nur für GET-Anfragen aus, deren Pfad genau /users ist. app.use('/users', fn) läuft für jede Methode und jeden Pfad, der mit /users beginnt, deshalb hängt man damit Router und Middleware ein.

Wie mache ich Express-Routen case-sensitive?

Routen ignorieren standardmäßig Groß- und Kleinschreibung, /Users passt also auf /users. Schalte das mit app.set('case sensitive routing', true) ab oder pro Router mit express.Router({ caseSensitive: true }).

Warum ist req.params in einem verschachtelten Router leer?

Ein Router sieht nur die Parameter seiner eigenen Pfade. Wenn er unter /users/:userId/posts eingehängt ist, erstell ihn mit express.Router({ mergeParams: true }), damit req.params.userId aus dem übergeordneten Pfad verfügbar ist.

Sollte ich alle Routen in eine Datei packen?

Nicht, sobald es mehr als eine Handvoll sind. Leg pro Ressource einen Router an (routes/users.js, routes/orders.js), exportier ihn mit module.exports = router und häng jeden in der Hauptdatei mit app.use() ein.

Illustration der Programmiersprachen bei Coddy

Lerne mit Coddy zu programmieren

Los geht's