Benutzerdefinierte Fehlerseiten von Node.js-Anwendungen
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
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.