REST-Webservices mit Node.js, Teil 2: Express als Anwendungsserver

Seite 2: Konfiguration

Inhaltsverzeichnis

Ein configure-Block lässt sich jedoch nicht nur verwenden, um kontextabhängig verschiedene Module zu laden, sondern auch um Konfigurationseinstellungen von Express vorzunehmen. Hierfür dienen die Funktionen app.set, app.enable und app.disable. Die set-Funktion erwartet zwei Parameter: einen Schlüssel und einen Wert, auf den der jeweilige Schlüssel gesetzt werden soll. Die beiden anderen Funktionen sind lediglich Abkürzungen für den Aufruf von

app.set('key', true);

beziehungsweise:

app.set('key', false);

Prinzipiell lassen sich als Schlüssel beliebige Bezeichner übergeben, was man beispielsweise zur externen Konfiguration von Modulen nutzen kann. Da das jedoch auch die entsprechende Set-up-Funktion des jeweiligen Moduls angehen kann, ist das häufiger auftretende Szenario, dass Express selbst konfiguriert werden soll. Hierfür stehen Schlüssel zur Verfügung, von denen die wichtigsten im Folgenden erläutert seien:

  • basepath: dient dazu, den Basispfad der Webanwendung festzulegen, der beispielsweise bei Umleitungen angewendet wird.
  • views: gibt das Verzeichnis an, in dem Express nach Vorlagen für dynamisch erzeugte Webseiten sucht.
  • view engine: gibt den Namen der Komponente an, die zum Erzeugen dynamischer Webseiten auf Basis von Vorlagen dient.
  • view caching: Wird der Schlüssel auf den Wert true gesetzt, aktiviert Express den Cache für Vorlagen.
  • case sensitive routes: Beim Setzen des Schlüssels auf den Wert true unterscheidet Express zwischen Groß- und Kleinschreibung innerhalb von Routendefinitionen.
  • strict routing: Wird der Schlüssel auf den Wert true gesetzt, werden abschließende Schrägstriche in Routendefinitionen nicht ignoriert.

Eine vollständige Liste aller verfügbaren Konfigurationseinstellungen findet sich in der Dokumentation von Express.

Bislang wurde lediglich die Route * verwendet, die als Platzhalter auf alle eingehenden Anfragen reagiert. Alternativ lassen sich aber Pfade verwenden, um beispielsweise eine virtuelle Verzeichnisstruktur in Express abzubilden:

app.get('/foo', function (req, res) {
// ...
});

Bei Bedarf kann der Entwickler auch verschiedene Routen für den gleichen Pfad definieren. Dann wird die in der Datei zuerst vorkommende verwendet. Wird dem Callback der Route wie bei Connect allerdings außer dem req- und dem res-Objekt die next-Funktion übergeben, ist es darüber möglich, die Ausführung an die nächste passende Route zu übergeben:

app.get('/foo', function (req, res, next) {
// ...
next();
});

Intern werden Routen als regulärer Ausdruck verarbeitet, sodass sich anstelle einer Zeichenkette auch direkt ein regulärer Ausdruck übergeben lässt, um beispielsweise Routen zu erzeugen, die auf ein bestimmtes Format der angeforderten Adresse reagieren:

app.get(/^\/foo/, function (req, res) {
// ...
});

Diese Route reagiert aufgrund des verwendeten regulären Ausdrucks /^\/foo/ auf alle eingehenden Anfragen, deren zugehörige Adresse mit /foo beginnt:

  • /foo
  • /foobar
  • /foo/bar
  • /foo.bar
  • ...

An der Stelle wird deutlich, wozu der erwähnte Aufruf des app.router-Moduls dient: Über die Reihenfolge der Moduldefinitionen kann die Verarbeitung der Routen beispielsweise vor oder nach einem statischen Dateiserver stattfinden. Findet der Aufruf von app.router vor der Integration des statischen Dateiservers statt, haben die Routen höhere Priorität als potenziell physisch vorhandene Dateien; ereignet er sich danach, greifen die Routen nur, wenn keine Datei des angeforderten Namens physisch existiert.

Routen lassen sich darüber hinaus parametrisieren, beispielsweise um einen REST-kompatiblen Endpunkt zu definieren, über den Datensätze anhand ihrer ID geladen werden können:

app.get('/foo/:id', function (req, res) {
// ...
});

Ein Parameter wird innerhalb einer Route durch einen Doppelpunkt eingeleitet, dann enthält die Route also einen Parameter, nämlich :id. Der Zugriff auf Parameter erfolgt innerhalb des Callbacks mit dem Objekt req.params, dem die einzelnen Parameter von Express hinzugefügt werden:

app.get('/foo/:id', function (req, res) {
console.log('id: ' + req.params.id);
// ...
});

Wird diese Route nun beispielsweise über die Adresse /foo/23 aufgerufen, enthält req.params.id den Wert 23. Als Trenner von Parametern dient standardmäßig der Schrägstrich. Der Aufruf der Adresse
/foo/23/5 passt daher nicht zur angegebenen Route, stattdessen wäre die Definition einer gesonderten Route erforderlich, die zwei Parameter erwartet:

app.get('/foo/:id/:subId', function (req, res) {
console.log('id: ' + req.params.id);
console.log('subId: ' + req.params.subId);
// ...
});

Bei Bedarf lassen sich Parameter als optional kennzeichnen, indem man ihnen das Suffix ? anhängt. Bei Definition der zuvor genannte Route also als

app.get('/foo/:id/:subId?', function (req, res) {

lässt sie sich sowohl mit einem als auch mit zwei Parametern aufrufen. Entfällt der zweite beim Aufruf, enthält req.params.subId den Wert undefined. Bemerkenswert ist, dass Parameter nicht nur als eigenständiges Routenfragment zwischen zwei Schrägstrichen auftreten können, sondern auch als Bestandteil eines Routenfragments. Beispielsweise lässt sich das Format einer Anfrage wie eine Dateiendung angeben:

app.get('/foo.:format', function (req, res) {

Diese Route lässt sich nun etwa mit /foo.xml und /foo.json aufrufen. Selbstverständlich kann ein solcher Parameter seinerseits wiederum optional sein:

app.get('/foo.:format?', function (req, res) {

Diese Route kann der Entwickler nun beispielsweise mit /foo.xml und /foo.json aufrufen – oder auch nur mit /foo, wobei dann der Punkt entfällt, da er lediglich das Trennzeichen zum zweiten, nicht vorhandenen Parameter darstellt.