Ich versuche, den gefürchteten Can't set headers after they are sent
Fehler in einer node.js Express-Anwendung zu debuggen. Insbesondere verwende ich die knox -Bibliothek, um mit s3 zu sprechen.
Grob gesagt habe ich diesen Express-Handler, der eine globale Instanz eines knox s3client verwendet:
%Vor% Wenn ich in Region A einen Header oder Statuscode auf res
anlege, funktioniert alles. Wenn ich irgendetwas davon in Region B versuche, bekomme ich den Fehler "Kann Header nicht setzen, nachdem sie gesendet wurden". Beachten Sie, dass ich Header für res
, nicht s3res
Vermutlich wird response.writeHead
irgendwo aufgerufen oder ausgelöst, bevor der On-Response-Callback des knox s3client aufgerufen wird. Gibt es ein Debug-Flag oder eine andere Möglichkeit, Node ausspucken zu lassen, wenn / wo writeHead aufgerufen wurde? Knoten 0.10 fügt ein response.headersSent
hinzu, aber es wäre unerschwinglich, meinen Code und alle Bibliotheken von Drittanbietern mit einer Überprüfung dieses Flags zu füllen, um herauszufinden, wo dieser aufgerufen wird. Oder gibt es sonst noch etwas, um dieses Problem zu lösen?
Sie könnten versuchen, eine einfache Middleware einzubinden, die einen Stack-Trace nach stdout ablegt, wenn writeHead
aufgerufen wird:
Sie müssen das vor Routen / Middleware einfügen, die Ihr Problem auslösen könnte.
FWIW, ich vermute, dass das Problem durch etwas ausgelöst wird, das in der Region C passiert (entweder ein res.send
, res.end
, res.json
oder res.render
, das dort aufgerufen wird):
BEARBEITEN Wenn s3res
ein richtiger Stream ist, können Sie Folgendes versuchen:
Beachten Sie jedoch, dass alle Header, die von der S3-Anforderung zurückgegeben werden, an die Express-Antwort übergeben werden.
Ich bin mir nicht sicher, ob das hier zutrifft, aber was ich sofort dachte, als ich den Fehler sah, war ein einfacher, sehr einfacher Fehler in der "Callback-Logik" irgendwo in der "Modellschicht". Ich hatte in zwei getrennten Fällen den Kopf darüber gekratzt, in beiden Fällen stellte sich heraus, dass ich einen Rückruf (d. H. Einen Anruf, der schließlich den Rückruf mit Rückmeldung schreiben würde) zweimal anrief. Dies würde nur bei einem Fehler in meiner Modellschicht passieren, weil es Code wie:
war %Vor% Wenn ich jetzt auf einen solchen Fehler stoßen würde, wäre das erste, was ich tun würde, zu überprüfen, ob der Rückmeldungs-Callback für eine Operation zweimal aufgerufen wird. Nur zwei console.log
-Anweisungen in der Region A (der Bereich, in dem die Knox-Anfrage initiiert wird) und einer in der Region C (der Antwort schreiben Callback) würden ausreichen, um diese Möglichkeit zumindest zu eliminieren.
Im Prinzip sollte Ihr Objekt res
ziemlich geschützt sein. Nur die Middleware connect / express hat Zugriff darauf und natürlich auf diesen speziellen Request-Handler. Es gibt also nur eine begrenzte Anzahl von Orten, die die Möglichkeit haben, einen Header zu schreiben.