Routing
Routing bezieht sich darauf, wie die Endpunkte einer Anwendung (URIs) auf Kundenanfragen reagieren. Für eine Einführung in das Routing siehe Basic routing.
Du definierst Routing, indem du Methoden des Express app Objekts verwendest, die den HTTP-Methoden entsprechen;
zum Beispiel, app.get() um GET-Anfragen und app.post zu behandeln, um POST-Anfragen zu bearbeiten. For a full list,
see app.METHOD. You can also use app.all() to handle all HTTP methods and app.use() to
specify middleware as the callback function (See Using middleware for details).
Mit anderen Worten, die Anwendung “lauscht” für Anforderungen, die mit der angegebenen Route(s) und Methode(n) übereinstimmen und wenn es ein Spiel erkennt, ruft es die angegebene Callback-Funktion auf. Mit anderen Worten, die Anwendung “lauscht” für Anforderungen, die mit der angegebenen Route(s) und Methode(n) übereinstimmen und wenn es ein Spiel erkennt, ruft es die angegebene Callback-Funktion auf.
In der Tat können die Routing-Methoden mehr als eine Callback-Funktion als Argumente haben.
Mit mehreren Callback-Funktionen, es ist wichtig, next als Argument für die Callback-Funktion zur Verfügung zu stellen und dann next() im Körper der Funktion aufzurufen, um die Steuerung
an den nächsten Callback zu übergeben.
Der folgende Code ist ein Beispiel für eine sehr einfache Route.
const express = require('express');const app = express();
// respond with "hello world" when a GET request is made to the homepageapp.get('/', (req, res) => { res.send('hello world');});import express from 'express';
const app = express();
// respond with "hello world" when a GET request is made to the homepageapp.get('/', (req, res) => { res.send('hello world');});import express, { type Express, type Request, type Response } from 'express';
const app: Express = express();
// respond with "hello world" when a GET request is made to the homepageapp.get('/', (req: Request, res: Response) => { res.send('hello world');});Routenmethoden
Eine Route-Methode wird von einer der HTTP-Methoden abgeleitet und an eine Instanz der Klasse express angehängt.
Der folgende Code ist ein Beispiel für Routen, die für die GET und die POST Methoden im Root der App definiert sind.
// GET method routeapp.get('/', (req, res) => { res.send('GET request to the homepage');});
// POST method routeapp.post('/', (req, res) => { res.send('POST request to the homepage');});import { type Request, type Response } from 'express';
// GET method routeapp.get('/', (req: Request, res: Response) => { res.send('GET request to the homepage');});
// POST method routeapp.post('/', (req: Request, res: Response) => { res.send('POST request to the homepage');});Express unterstützt Methoden, die allen HTTP-Anfragemethoden entsprechen: get, post und so weiter.
For a full list, see app.METHOD.
Es gibt eine spezielle Routing-Methode, app.all(), die benutzt wird, um Middleware-Funktionen an einem Pfad für all HTTP-Requestmethoden zu laden. For example, the following handler is executed for requests to the route "/secret" whether using GET, QUERY, POST, PUT, DELETE, or any other HTTP request method supported in the http module.
app.all('/secret', (req, res, next) => { console.log('Accessing the secret section ...'); next(); // pass control to the next handler});import { type Request, type Response, type NextFunction } from 'express';
app.all('/secret', (req: Request, res: Response, next: NextFunction) => { console.log('Accessing the secret section ...'); next(); // pass control to the next handler});Routenpfade
Routenpfade in Kombination mit einer Anfragemethode definieren die Endpunkte, an denen Anfragen gestellt werden können. Routenpfade können Strings oder reguläre Ausdrücke sein. They can also capture values from the URL, as described in Route parameters below.
Note
Express verwendet path-to-regexp v8 um die Routenpfade zu treffen; lesen Sie die Dokumentation zu regexp für alle Möglichkeiten bei der Definition von Routenpfaden. Express Playground Router ist ein praktisches Werkzeug zum Testen grundlegender Express-Routen, obwohl es kein Muster-Matching unterstützt.
Stringpfade
String Pfade entsprechen exakt den Anforderungen. Der Punkt (.) und der Bindestrich (-) werden wörtlich interpretiert.
Warning
app.get('/', (req, res) => { res.send('root');});
app.get('/about', (req, res) => { res.send('about');});
app.get('/random.text', (req, res) => { res.send('random.text');});import { type Request, type Response } from 'express';
app.get('/', (req: Request, res: Response) => { res.send('root');});
app.get('/about', (req: Request, res: Response) => { res.send('about');});
app.get('/random.text', (req: Request, res: Response) => { res.send('random.text');});Caution
The characters ?, +, *, [], (), and ! are reserved and cannot be used as literal characters in route paths, and braces are reserved for optional segments. Benutze \, um sie bei Bedarf zu maskieren.
Reguläre Ausdrücke
Sie können auch reguläre Ausdrücke als Routenpfade verwenden. Dies ist nützlich, wenn Sie eine komplexere Abgleichlogik benötigen.
// Matches any path containing "a"app.get(/a/, (req, res) => { res.send('/a/');});
// Matches paths ending with "fly" (butterfly, dragonfly, etc.)app.get(/.*fly$/, (req, res) => { res.send('/.*fly$/');});import { type Request, type Response } from 'express';
// Matches any path containing "a"app.get(/a/, (req: Request, res: Response) => { res.send('/a/');});
// Matches paths ending with "fly" (butterfly, dragonfly, etc.)app.get(/.*fly$/, (req: Request, res: Response) => { res.send('/.*fly$/');});Routenparameter
Routenparameter sind URL-Segmente, die zur Erfassung der an ihrer Position in der URL angegebenen Werte verwendet werden. Die erfassten Werte werden im Objekt req.params gefüllt, wobei der Name des im Pfad angegebenen Routenparameter als ihre jeweiligen Schlüssel angegeben ist. They come in three forms: named parameters (:name), wildcards (*name), and optional segments, which wrap either of them in braces.
Named parameters
Named parameters capture a single path segment at their position in the URL, or part of one when combined with literal characters, as shown further below.
Route path: /users/:userId/books/:bookIdRequest URL: http://localhost:3000/users/34/books/8989req.params: { "userId": "34", "bookId": "8989" }Um Routen mit Routenparametern zu definieren, geben Sie einfach die Routenparameter im Pfad der Route, wie unten gezeigt, an.
app.get('/users/:userId/books/:bookId', (req, res) => { res.send(req.params);});In TypeScript, @types/express infers the parameters from the route path, so in the handler above
req.params.userId and req.params.bookId are already typed as string with no extra annotation.
Reading a name that is not in the route (such as req.params.other) is a type error. You only need
to annotate the parameters when the handler is defined separately from the route, because the type
checker can no longer see the path. In that case, pass them as the first type argument of Request:
import { type Request, type Response } from 'express';
const sendParams = (req: Request<{ userId: string; bookId: string }>, res: Response) => { res.send(req.params);};
app.get('/users/:userId/books/:bookId', sendParams);Caution
The name of route parameters must be a valid JavaScript identifier. Other names can be used by quoting them, for example :"user-name".
Da die Bindestriche (-) und der Punkt (.) wörtlich interpretiert werden, können sie zusammen mit Routenparametern für nützliche Zwecke verwendet werden.
Route path: /flights/:from-:toRequest URL: http://localhost:3000/flights/LAX-SFOreq.params: { "from": "LAX", "to": "SFO" }Route path: /plantae/:genus.:speciesRequest URL: http://localhost:3000/plantae/Prunus.persicareq.params: { "genus": "Prunus", "species": "persica" }Caution
Regexp characters are not supported inside string paths, so a parameter cannot be restricted with a suffix such as :userId(\d+). Use an array of paths or a full regular expression instead.
Weitere Informationen finden Sie in der Syntax Pfadroute Match.
Wildcards
Platzhalter entsprechen jedem Pfad nach einem Präfix. Like other route parameters they must have a name, but they are captured as an array of path segments instead of a string.
app.get('/files/*filepath', (req, res) => { // GET /files/images/logo.png console.dir(req.params.filepath); // => [ 'images', 'logo.png' ] res.send(`File: ${req.params.filepath.join('/')}`);});import { type Request, type Response } from 'express';
app.get('/files/*filepath', (req: Request<{ filepath: string[] }>, res: Response) => { // GET /files/images/logo.png console.dir(req.params.filepath); // => [ 'images', 'logo.png' ] res.send(`File: ${req.params.filepath.join('/')}`);});Um auch dem Wurzelpfad zu entsprechen, wickeln Sie den Platzhalter in Klammern:
// Matches / , /foo , /foo/bar , etc.app.get('/{*splat}', (req, res) => { // GET / => req.params = {}, splat is omitted // GET /foo/bar => req.params.splat = [ 'foo', 'bar' ] res.send('ok');});import { type Request, type Response } from 'express';
// Matches / , /foo , /foo/bar , etc.app.get('/{*splat}', (req: Request, res: Response) => { // GET / => req.params = {}, splat is omitted // GET /foo/bar => req.params.splat = [ 'foo', 'bar' ] res.send('ok');});Optionale Segmente
Verwenden Sie Klammern um optionale Segmente in einem Routenpfad zu definieren. Wenn das Segment nicht vorhanden ist, wird der Parameter von req.params weggelassen.
app.get('/:file{.:ext}', (req, res) => { // GET /image.png => req.params = { file: 'image', ext: 'png' } // GET /image => req.params = { file: 'image' } res.send('ok');});import { type Request, type Response } from 'express';
app.get('/:file{.:ext}', (req: Request, res: Response) => { // GET /image.png => req.params = { file: 'image', ext: 'png' } // GET /image => req.params = { file: 'image' } res.send('ok');});The braces can also wrap a whole parameter to make it optional. Note that everything inside the braces is optional, so the position of the slash matters:
app.get('/user/{:id}', (req, res) => { // GET /user/42 => req.params = { id: '42' } // GET /user/ => req.params = {} // GET /user => 404, only the parameter is optional res.send('ok');});
app.get('/order{/:id}', (req, res) => { // GET /order/42 => req.params = { id: '42' } // GET /order => req.params = {}, the whole segment is optional res.send('ok');});import { type Request, type Response } from 'express';
app.get('/user/{:id}', (req: Request, res: Response) => { // GET /user/42 => req.params = { id: '42' } // GET /user/ => req.params = {} // GET /user => 404, only the parameter is optional res.send('ok');});
app.get('/order{/:id}', (req: Request, res: Response) => { // GET /order/42 => req.params = { id: '42' } // GET /order => req.params = {}, the whole segment is optional res.send('ok');});Verwechsle die Position des Schrägstrichs im Routenpfad nicht mit der strict routing-Einstellung, die sich auf die Anfrage-URL bezieht: Sie steuert, ob eine URL, die mit einem Schrägstrich endet, den der Routenpfad nicht verlangt, trotzdem übereinstimmt. Zum Beispiel stimmt eine Anfrage an /order/ standardmäßig mit der Route /order{/:id} überein, gibt aber einen 404-Fehler zurück, wenn strict routing aktiviert ist; der abschließende Schrägstrich von /user/ ist davon nicht betroffen, weil die Route /user/{:id} ihn verlangt. Alle in den obigen Beispielen kommentierten Anfragen verhalten sich unabhängig von dieser Einstellung gleich.
Routenhandler
Du kannst mehrere Callback-Funktionen bereitstellen, die sich wie middleware verhalten um eine Anfrage zu bearbeiten. Die einzige Ausnahme ist, dass diese Callbacks next('route') aufrufen könnten, um die restlichen Rufnummern zu umgehen. Sie können diesen Mechanismus nutzen, um Vorbedingungen auf einer Route aufzuerlegen, dann die Kontrolle an die nachfolgenden Routen übergeben, wenn es keinen Grund gibt, mit der aktuellen Route fortzufahren.
app.get('/user/:id', (req, res, next) => { if (req.params.id === '0') { return next('route'); } res.send(`User ${req.params.id}`);});
app.get('/user/:id', (req, res) => { res.send('Special handler for user ID 0');});import { type Request, type Response, type NextFunction } from 'express';
app.get('/user/:id', (req: Request, res: Response, next: NextFunction) => { if (req.params.id === '0') { return next('route'); } res.send(`User ${req.params.id}`);});
app.get('/user/:id', (req: Request, res: Response) => { res.send('Special handler for user ID 0');});In diesem Beispiel:
GET /user/5→ behandelt durch die erste Route → sendet “Benutzer 5”GET /user/0→ erste Routenaufrufenext('route'), überspringt zur nächsten passenden/user/:idRoute
Routenhandler können in Form einer Funktion, eines Arrays von Funktionen oder Kombinationen beider sein, wie in den folgenden Beispielen gezeigt.
Eine einzelne Callback-Funktion kann eine Route handhaben. Zum Beispiel:
app.get('/example/a', (req, res) => { res.send('Hello from A!');});import { type Request, type Response } from 'express';
app.get('/example/a', (req: Request, res: Response) => { res.send('Hello from A!');});Mehr als eine Callback-Funktion kann eine Route handhaben (stelle sicher, dass du das next Objekt angibst). Zum Beispiel:
app.get( '/example/b', (req, res, next) => { console.log('the response will be sent by the next function ...'); next(); }, (req, res) => { res.send('Hello from B!'); });import { type Request, type Response, type NextFunction } from 'express';
app.get( '/example/b', (req: Request, res: Response, next: NextFunction) => { console.log('the response will be sent by the next function ...'); next(); }, (req: Request, res: Response) => { res.send('Hello from B!'); });Ein Array von Callback-Funktionen kann eine Route handhaben. Zum Beispiel:
const cb0 = function (req, res, next) { console.log('CB0'); next();};
const cb1 = function (req, res, next) { console.log('CB1'); next();};
const cb2 = function (req, res) { res.send('Hello from C!');};
app.get('/example/c', [cb0, cb1, cb2]);import { type Request, type Response, type NextFunction } from 'express';
const cb0 = function (req: Request, res: Response, next: NextFunction) { console.log('CB0'); next();};
const cb1 = function (req: Request, res: Response, next: NextFunction) { console.log('CB1'); next();};
const cb2 = function (req: Request, res: Response) { res.send('Hello from C!');};
app.get('/example/c', [cb0, cb1, cb2]);Eine Kombination aus unabhängigen Funktionen und Arrays von Funktionen kann eine Route handhaben. Zum Beispiel:
const cb0 = function (req, res, next) { console.log('CB0'); next();};
const cb1 = function (req, res, next) { console.log('CB1'); next();};
app.get( '/example/d', [cb0, cb1], (req, res, next) => { console.log('the response will be sent by the next function ...'); next(); }, (req, res) => { res.send('Hello from D!'); });import { type Request, type Response, type NextFunction } from 'express';
const cb0 = function (req: Request, res: Response, next: NextFunction) { console.log('CB0'); next();};
const cb1 = function (req: Request, res: Response, next: NextFunction) { console.log('CB1'); next();};
app.get( '/example/d', [cb0, cb1], (req: Request, res: Response, next: NextFunction) => { console.log('the response will be sent by the next function ...'); next(); }, (req: Request, res: Response) => { res.send('Hello from D!'); });Antwortmethoden
The methods on the response object (res) in the following table can send a response to the client, and terminate the request-response cycle. Wenn keine dieser Methoden von einem Routenhandler aufgerufen wird, bleibt die Client-Anfrage hängen.
| Methode | Beschreibung |
|---|---|
| res.download() | Fordern Sie eine Datei zum Download an. |
| res.end() | Beenden Sie den Antwort-Prozess. |
| res.json() | Sende eine JSON-Antwort. |
| res.jsonp() | Senden Sie eine JSON-Antwort mit JSONP-Unterstützung. |
| res.redirect() | Anfrage umleiten. |
| res.render() | Render a view template. |
| res.send() | Senden Sie eine Antwort von verschiedenen Typen. |
| res.sendFile() | Senden Sie eine Datei als octet-Stream. |
| res.sendStatus() | Legen Sie den Antwort-Statuscode fest und senden Sie seine Zeichenfolge Repräsentation als Antwortkörper. |
app.route()
Sie können verkettende Routenhandler für einen Routenpfad erstellen, indem Sie app.route() verwenden.
Because the path is specified in a single location, this helps to create modular routes and reduces redundancy and typos. For more information about routes, see the Router() documentation.
Hier ist ein Beispiel für verkettete Routenhandler, die mit app.route() definiert werden.
app .route('/book') .get((req, res) => { res.send('Get a random book'); }) .post((req, res) => { res.send('Add a book'); }) .put((req, res) => { res.send('Update the book'); });import { type Request, type Response } from 'express';
app .route('/book') .get((req: Request, res: Response) => { res.send('Get a random book'); }) .post((req: Request, res: Response) => { res.send('Add a book'); }) .put((req: Request, res: Response) => { res.send('Update the book'); });express.Router
Verwende die Klasse express.Router, um modulare mountbare Routenhandler zu erstellen. Eine Router-Instanz ist ein komplettes Middleware- und Routing-System; aus diesem Grund wird sie oft als “Mini-App” bezeichnet.
Das folgende Beispiel erzeugt einen Router als Modul, lädt eine Middleware-Funktion darin definiert einige Routen und mountet das Router-Modul auf einem Pfad in der Hauptanwendung.
Erstelle eine Router-Datei namens birds.js im App-Verzeichnis, mit folgendem Inhalt:
const express = require('express');const router = express.Router();
// middleware that is specific to this routerconst timeLog = (req, res, next) => { console.log('Time: ', Date.now()); next();};router.use(timeLog);
// define the home page routerouter.get('/', (req, res) => { res.send('Birds home page');});// define the about routerouter.get('/about', (req, res) => { res.send('About birds');});
module.exports = router;import express from 'express';
const router = express.Router();
// middleware that is specific to this routerconst timeLog = (req, res, next) => { console.log('Time: ', Date.now()); next();};router.use(timeLog);
// define the home page routerouter.get('/', (req, res) => { res.send('Birds home page');});// define the about routerouter.get('/about', (req, res) => { res.send('About birds');});
export default router;import express, { type Request, type Response, type NextFunction } from 'express';
const router = express.Router();
// middleware that is specific to this routerconst timeLog = (req: Request, res: Response, next: NextFunction) => { console.log('Time: ', Date.now()); next();};router.use(timeLog);
// define the home page routerouter.get('/', (req: Request, res: Response) => { res.send('Birds home page');});// define the about routerouter.get('/about', (req: Request, res: Response) => { res.send('About birds');});
export default router;Laden Sie dann das Router-Modul in der App:
const birds = require('./birds');
// ...
app.use('/birds', birds);import birds from './birds';
// ...
app.use('/birds', birds);Die App wird nun in der Lage sein, Anfragen an /birds und /birds/about zu bearbeiten, aufrufen sowie die Middleware-Funktion timeLog aufrufen, die spezifisch für die Route ist.
Aber wenn die übergeordnete Route /birds Pfadparameter hat, wird sie standardmäßig nicht von den Unterrouten aus erreichbar sein. To make it accessible, you will need to pass the mergeParams option to the Router constructor.
const router = express.Router({ mergeParams: true });