ここで起こっていることを分解しましょう
wrapping idiom to hook into the call to writeHead
通常のExpressフローでは、リクエスト ( req ) を受け取り、レスポンス ( res ) を準備します。( req , res ) ペアは、 reqを変更してresを準備できる一連のフィルターを介してカスケードできます。
フローのある時点で、resは、応答のヘッダーをクライアントに送信できるように十分に準備されていると見なされます。関数res.writeHead * がその目的で呼び出されます。
この関数のプロトタイプはfunction (code, headers)です。送信されるヘッダーをログに記録するには、この瞬間にコードをフックして、
console.log("Response " + code + " " + JSON.stringify(headers));
ある意味で、コード内の元の関数が
res.writeHead = function(code, headers) {
// original code
}
このコードを
res.writeHead = function(code, headers) {
console.log("Response " + code + " " + JSON.stringify(headers));
// original code
}
ある意味では、writeHead 関数の先頭にコードのスニペットを「挿入」する必要があります。
しかし、元の writeHead コードを変更しようとしてはいけません。なぜなら、このコードがどこに書かれているかさえわからず、探したくないからです。したがって、この関数をハイジャックしたい場合: コードの一部が res.writeHead を呼び出す場合、代わりに関数を呼び出す必要があります。
これへの方法は単純です
return function logItHandle(req, res, next) {
res.writeHead = function (code, headers) {
console.log("Response " + code + " " + JSON.stringify(headers));
}
next();
}
ただし、これだけを行うと、元の writeHead コードが失われ、呼び出されないため、少し問題が発生します。したがって、ヘッダーはログに記録されますが、クライアントには送信されません!
元のコードを「記憶」し、writeHead variant の最後に呼び出す方法が必要です。
return function logItHandle(req, res, next) {
// save the original writeHead function so that it can be referenced in the closure
var originalWriteHead = res.writeHead;
res.writeHead = function (code, headers) {
// log the response headers
console.log("Response " + code + " " + JSON.stringify(headers));
// make as if our hook never existed in the flow
res.writeHead = originalWriteHead ;
// call the original writeHead because otherwise the external code
// called our implementation of writeHead instead of the original code
res.writeHead(code, headers);
}
next();
}