Benutzerdefinierte Fehlerseiten von Node.js-Anwendungen

3 Minuten Lesezeit

Eine typische Anforderung in Web-Projekten ist häufig die Darstellung von benutzerdefinierten Fehlerseiten für beispielsweise HTTP 404- oder HTTP 500-Fehler. Setzt man in Node.js auf das leichtgewichtige und weit verbreitete MVC-Framework express, so ist das auch mit wenigen Handgriffen umgesetzt. Nun wird man sich aber vermutlich wundern wo diese Fehlermeldungen nach dem Bereitstellen in Windows Azure geblieben sind. Die Lösung ist dabei relativ simpel.

Benutzerdefinierte Fehlerseiten in express

Beipiel 404-Fehler

Registrierung der Fehler-Handler

Das Registrieren der Fehler-Handler erfolgt hinter allen anderen Middlewares. Im Beispiel unten muss auf die Methoden-Signaturen geachtet werden.

Bei einem HTTP 404-Fehler wird der Status manuell auf 404 gesetzt und eine View mit dem Namen 404 dargestellt. Diese Methode wird aufgerufen, wenn der Request vorher noch von keiner Middleware bearbeitet wurde. Dies bedeutet auch, dass es sich hierbei eigentlich nicht um einen Fehler handelt und somit kein err-Parameter gebraucht wird.

Bei anderen Server-Fehlern, wie zum Beispiel HTTP 500, greift dann die untere Middleware. Dabei wird in der Anwendung mithilfe von throw ein Fehler-Objekt geworfen, welches sich im Parameter err wiederfindet. Ist ein Status gesetzt, so findet sich dieser als Statuscode in der Response wieder. Als Standard-Status ist 500 eingestellt und es wird die View 500 gerendert. Das Fehler-Objekt könnte hier um beliebige Felder erweitert werden.

app.use(function (req, res, next) {
    res.status(404).render('404');
});

app.use(function (err, req, res, next) {
    console.error(err.stack);
    res.status(err.status || 500).render('500');
});

Werfen von HTTP 400

Kann nun eine Route nicht gefunden werden, so wird schließlich der HTTP 404-Handler ausgeführt und somit die View 404.html oder 404.jade, je nach Layout-Engine, geladen.

Oft wird eine passende Route gefunden, es kann allerdings erst in dieser entschieden werden, ob eine Ressource existiert oder auch nicht. In diesem Fall muss in der Controller-Methode der next-Parameter existieren und mit return next() an die nächste Middleware in der Pipeline verwiesen werden. Dieser Vorgang simuliert das Verhalten einer nicht gefunden Route.

function (req, res, next) {
    if (!someNotFoundDatabaseEntity) {
        return next();
    }
}

Werfen von HTTP 500

Der HTTP 500-Handler wird aufgerufen, wenn ein Error mittels throw geworfen wurde. Am Fehler-Objekt sollte eine Eigenschaft status auf den gewünschten Status-Code gesetzt werden. Dieser Status-Code wird dem Webbrowser in der Response übermittelt.

Aktivieren der benutzerdefinierten Fehlerseiten in Windows Azure

Wenn die Anwendung nun in Windows Azure läuft so erscheint bei 404-Fehlern standardmäßig einfach nur die Meldung 'The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.' Auch 505-Fehler zeigen nur einen nicht formatierten Text an. Die implementierten benutzerdefinierten und an das Seiten-Layout angepassten Fehlermeldungen werden dabei ignoriert.

node.js läuft innerhalb des IIS und dieser hat in den Standardeinstellungen die Erlaubnis seine benutzerdefinierten Fehlermeldungen anzuzeigen. Die von node.js werden somit einfach überschrieben.

Dieses Verhalten kann natürlich umgestellt werden. Hierfür muss die Datei web.config angepasst werden.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <httpErrors existingResponse="PassThrough" /> <!-- Aktivierung von benutzerdefinierten Fehlerseiten in node.js -->

    <handlers>
      <add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
    </handlers>

    <rewrite>
      <rules>
        <rule name="StaticContent">
          <action type="Rewrite" url="public{{REQUEST_URI}}"/>
        </rule>
        <rule name="DynamicContent">
          <conditions>
            <add input="{{REQUEST_FILENAME}}" matchType="IsFile" negate="True"/>
          </conditions>
          <action type="Rewrite" url="server.js"/>
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Die Zeile <httpErrors existingResponse="PassThrough" /> im Beispiel oben ist die entscheidende. Der Tag befindet sich in der Konfiguration an der Stelle configuration/system.webServer/httpErrors. Der restliche XML-Inhalt ist nur beispielhaft und kann im eigenen Projekt abweichen.


comments powered byDisqus