Startseite / Artikel / Identifizieren versus Formen: Auswahl von Route-Parametern oder Abfragesätzen in Express

Identifizieren versus Formen: Auswahl von Route-Parametern oder Abfragesätzen in Express

Erfahren Sie, wann ein Wert in einen Express-Route-Parameter oder in eine Abfragesuche gehört, wie Sie req.params und req.query lesen sowie wie Sie Sicherheitsmechanismen für Standardwerte und Datentypen nutzen.

1324 Wörter

Nehmen Sie die URL /users/42?sort=name&order=asc. Die Zahl 42 bezeichnet einen bestimmten Benutzer; sort=name&order=asc ändert lediglich die Anordnung der Antwort. Wenn man diese beiden Funktionen verwechselt – beispielsweise einen ID als Filter oder einen Filter als ID verwendet – entstehen typischerweise unhandliche Express-Routen. Nach dem Lesen dieses Leitfadens haben Sie einen einfachen Test, um zu entscheiden, wohin ein Wert gehört, und wissen, wie Express jede Art von Parameter darstellt sowie welche Überraschungen damit verbunden sein können.

Routenparameter identifizieren eine Ressource

Ein Routenparameter ist ein benannter Teil des Pfadmusters selbst. Er gibt dem Server an, um welche spezifische Ressource sich die Anfrage dreht.

/users/:id

Das Kolon markiert :id als Platzhalter. Wenn eine Anfrage an /users/42 eingeht, passt Express das Muster ab und speichert 42 als Wert für id. Dasselbe Prinzip gilt für jede Ressource, die eine Identität hat:

/users/42        → which user
/products/17      → which product
/orders/1042      → which order

Jeder dieser Pfade bezeichnet genau eine Sache. Ohne diesen Teil hat die Frage „Welche?“ keine Antwort.

Abfragesätze gestalten die Antwort

Ein Abfragesatz ist alles, was nach dem ? kommt: eine Liste von key=value-Paaren, die durch & verbunden sind. Er wählt keine Ressource aus, sondern filtert, sortiert, paginiert oder passt auf andere Weise das Zurückgegebene an.

/users?sort=name&order=asc

Hier lassen sort und order die Ressource (die Benutzerkollektion) unverändert und beeinflussen nur ihre Darstellung. Typischere Beispiele:

/products?category=electronics&maxPrice=500
/search?q=laptop&page=2

Ein einziges Fragestück zur Unterscheidung

Fragen Sie, was passiert, wenn der Wert gelöscht wird:

  • Falls die Route dann nicht mehr sinnvoll ist (man kann keinen „Benutzer“ abrufen, ohne anzugeben, um welchen es geht), handelt es sich um einen Identifikator, der im Pfad stehen sollte.
  • Falls die Route weiterhin funktioniert und einfach das standardmäßige, unfiltrierte Ergebnis zurückgibt (alle Benutzer in der üblichen Reihenfolge), handelt es sich um einen Modifikator, der im Abfragesatz stehen sollte.

Dieser Test gibt auch Hinweise zur Fehlerbehandlung. Ein fehlender Ressourcename hinter einem Route-Parameter sollte in der Regel mit 404 beantwortet werden, während ein Filter, der nichts findet, normalerweise mit 200 und einer leeren Liste zurückgeben sollte. Für einen umfassenderen Überblick über das ressourcenorientierte URL-Design siehe REST APIs für Anfänger.

Lesen von Route-Parametern mit req.params

Parameter werden im Route-Pfad mit einem Doppelpunkt deklariert, und ihre erfassten Werte erscheinen unter denselben Namen in req.params:

app.get("/users/:id", (req, res) => {
  const userId = req.params.id;
  res.send(`Fetching user with ID: ${userId}`);
});

Eine Anfrage an /users/42 setzt req.params.id auf den String "42".

Mehrere Parameter in einem Pfad

Eingebettete Ressourcen deklarieren einfach weitere Platzhalter:

app.get("/users/:userId/orders/:orderId", (req, res) => {
  const { userId, orderId } = req.params;
  res.send(`User ${userId}, Order ${orderId}`);
});

Für /users/42/orders/1042 ergibt die Destructuring-Operation userId mit dem Wert "42" und orderId mit dem Wert "1042". Parameternamen müssen innerhalb einer Route eindeutig sein und sollten beschreiben, was sie identifizieren; userId und orderId sind weitaus verständlicher als zwei anonyme id-Werte.

Lesen von Abfragesätzen mit req.query

Die Werte der Abfragen müssen in der Route nicht deklariert werden. Express analysiert alles, was nach dem ? kommt, und legt es in req.query ab:

app.get("/users", (req, res) => {
  const { sort, order } = req.query;
  res.send(`Sorting by ${sort}, order: ${order}`);
});

Für /users?sort=name&order=asc erhält man req.query.sort mit dem Wert "name" und req.query.order mit dem Wert "asc". Die Route bleibt weiterhin /users, sodass derselbe Handler sowohl die normale als auch die sortierte Anfrage bearbeitet.

Standardwerte für optionale Werte bereitstellen

Weil Clients oft keine Abfragewerte angeben, greifen Handler in der Regel auf sinnvolle Standardwerte zurück:

app.get("/products", (req, res) => {
  const sort = req.query.sort || "default";
  const page = req.query.page || 1;
  res.send(`Sorting: ${sort}, Page: ${page}`);
});

Eine reine /products-Anfrage funktioniert dennoch, wobei die Ersatzwerte verwendet werden. Beachten Sie eine Nuance: Wenn der Client tatsächlich page=2 sendet, ist page der String "2", wird er jedoch weggelassen, ist es die Zahl 1. Solche gemischten Typen verursachen später Fehler (zum Beispiel String-Konkatenation anstelle von Addition). Konvertieren Sie explizit, beispielsweise mit Number(req.query.page) || 1, und überprüfen Sie das Ergebnis, bevor Sie es in einer Datenbankabfrage verwenden.

Werte sind nicht immer einzelne Strings

Eine im URL wiederholte Schlüsselwörter, wie ?tag=a&tag=b, werden als Array statt als Zeichenkette übermittelt. Je nach Einstellung des Abfragesparsers kann die Klammersyntax auch verschachtelte Objekte erzeugen. Express 5 hat den Standardparser durch einen einfacheren ersetzt als der in Express 4 verwendet wurde, daher sollten Sie die Dokumentation für Ihre Version prüfen, falls Sie auf verschachtelte Abfrageobjekte angewiesen sind. In jedem Fall sollten Sie niemals den Typ eines Abfragewerts voraussetzen; behandeln Sie req.query als unzuverlässige Eingabe.

Auswahl des benötigten Formats für eine Route

Pfadparameter für eine bestimmte Ressource

app.get("/users/:id", ...)          // one specific user
app.get("/products/:id", ...)       // one specific product
app.get("/orders/:orderId", ...)    // one specific order

Jede dieser Routen bezieht sich auf ein einzelnes, konkretes Element. Wenn die Route ohne diesen Wert sinnlos ist, sollten Sie ihn in den Pfad aufnehmen.

Abfragesätze zur Filterung, Sortierung und Paginierung

app.get("/users", ...)     // ?role=admin&status=active
app.get("/products", ...)  // ?category=electronics&maxPrice=500&sort=price
app.get("/search", ...)    // ?q=laptop&page=2

Jeder dieser Ausdrücke macht auch ohne jegliche Abfrage Sinn: „alle Benutzer“, „alle Produkte“ oder eine leere Suchseite. Werte, die lediglich die Ergebnisse eingrenzen oder neu ordnen, sind optionale Modifikatoren und gehören nach dem ?.

Kombination beider in einer Route

Echte Endpunkte verwenden häufig beide gleichzeitig. Der Parameter wählt den Eigentümer aus, die Abfrage grenzt die damit verbundenen Daten ein:

app.get("/users/:id/orders", (req, res) => {
  const userId = req.params.id;         // which user
  const status = req.query.status;      // optional filter: only their pending orders, for example

  res.send(`Orders for user ${userId}, filtered by status: ${status || "all"}`);
});

Eine Anfrage an /users/42/orders?status=pending liest sich natürlich: 42 gibt an, zu wessen Bestellungen es geht, und status=pending legt fest, welche dieser Bestellungen berücksichtigt werden sollen. Wenn status fehlt, gibt der Handler „alle“ an, was der Vorstellung entspricht, dass das Fehlen eines Modifikators auf unfiltrierte Ergebnisse hindeutet.

Häufige Fragen

Kann eine Route beides verwenden?

Ja, und das ist sehr häufig. Das obige kombinierte Beispiel zeigt das typische Muster: ein Identifikator für die übergeordnete Ressource plus optionaler Filter für ihre Kinder.

Sind Parameter immer erforderlich und sind Abfragenwerte immer optional?

Das ist eine starke Konvention, keine strenge Regel. Express unterstützt tatsächlich optionale Pfadsegmente, und nichts hindert eine API daran, einen Abfragenwert zu verlangen. Dennoch gilt die praktische Richtlinie: Erforderliche Identifikatoren kommen im Pfad vor, optionale Modifizierer in der Abfrage mit Standardwerten.

Ist req.params.id eine Zahl?

Nein. Alles, was aus einer URL extrahiert wird, ist eine Zeichenkette – auch dann, wenn es numerisch aussieht. Konvertieren Sie es explizit, zum Beispiel mit Number(req.params.id), und lehnen Sie Werte ab, die als NaN herauskommen, bevor Sie die Datenbank aufrufen.

Was passiert, wenn ein erwarteter Abfragenwert fehlt?

Der Schlüssel fehlt einfach in req.query, wodurch die Lektüre desselben den Wert undefined ergibt. Genau deshalb sind die zuvor gezeigten Standardwerte eine übliche Praxis.

Zusammenfassung

Sowohl Arten von Werten befinden sich in derselben URL, erfüllen aber unterschiedliche Funktionen. Route-Parameter, die aus req.params abgerufen werden, geben an, worum es in einer Anfrage geht. Abfragesätze, die aus req.query abgerufen werden, steuern, wie die Antwort gefiltert, sortiert oder paginiert wird, und sollten Standardwerte haben. Behandeln Sie beide als untypisierte Zeichenketten aus der Außenwelt: Konvertieren und validieren Sie sie vor der Verwendung, damit das Routing-Design auch bei wachsender API weiterhin vorhersehbar bleibt.

Weitere Literatur

  • Vom Upload bis zur URL: Sicheres Speichern und Zustellen von Nutzerdateien in Express — Erfahren Sie, wo Express-Anwendungen hochgeladene Dateien speichern sollten, wie express.static eine Verzeichnisstruktur in URLs umwandelt und welche Schutzmaßnahmen verhindern, dass Nutzeruploads zu Sicherheitslücken werden.