express cuerpo de respuesta de registro

El título debería ser bastante auto explicativo.

Para fines de depuración, me gustaría que Express imprima el código y el cuerpo de respuesta para cada solicitud atendida. Imprimir el código de respuesta es bastante fácil, pero imprimir el cuerpo de la respuesta es más complicado, ya que parece que el cuerpo de la respuesta no está disponible como una propiedad.

Lo siguiente NO funciona:

var express = require('express'); var app = express(); // define custom logging format express.logger.format('detailed', function (token, req, res) { return req.method + ': ' + req.path + ' -> ' + res.statusCode + ': ' + res.body + '\n'; }); // register logging middleware and use custom logging format app.use(express.logger('detailed')); // setup routes app.get(..... omitted ...); // start server app.listen(8080); 

Por supuesto, podría imprimir fácilmente las respuestas en el cliente que emitió la solicitud, pero preferiría hacerlo también en el servidor.

PD: Si ayuda, todas mis respuestas son json, pero espero que haya una solución que funcione con respuestas generales.

No estoy seguro si es la solución más simple, pero puede escribir un middleware para interceptar los datos escritos en la respuesta. Asegúrese de desactivar app.compress() .

 function logResponseBody(req, res, next) { var oldWrite = res.write, oldEnd = res.end; var chunks = []; res.write = function (chunk) { chunks.push(chunk); oldWrite.apply(res, arguments); }; res.end = function (chunk) { if (chunk) chunks.push(chunk); var body = Buffer.concat(chunks).toString('utf8'); console.log(req.path, body); oldEnd.apply(res, arguments); }; next(); } app.use(logResponseBody); 

Me encontré con un problema utilizando el enfoque sugerido por Laurent. A veces, el fragmento es una cadena y, por lo tanto, causa problemas en la llamada a Buffer.concat (). De todos modos, encontré una ligera modificación de cosas arregladas:

 function logResponseBody(req, res, next) { var oldWrite = res.write, oldEnd = res.end; var chunks = []; res.write = function (chunk) { chunks.push(new Buffer(chunk)); oldWrite.apply(res, arguments); }; res.end = function (chunk) { if (chunk) chunks.push(new Buffer(chunk)); var body = Buffer.concat(chunks).toString('utf8'); console.log(req.path, body); oldEnd.apply(res, arguments); }; next(); } app.use(logResponseBody); 

Puede usar express-winston y configurar usando:

 expressWinston.requestWhitelist.push('body'); expressWinston.responseWhitelist.push('body'); 

Ejemplo en coffeescript:

 expressWinston.requestWhitelist.push('body') expressWinston.responseWhitelist.push('body') app.use(expressWinston.logger({ transports: [ new winston.transports.Console({ json: true, colorize: true }) ], meta: true, // optional: control whether you want to log the meta data about the request (default to true) msg: "HTTP {{req.method}} {{req.url}}", // optional: customize the default logging message. Eg "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}" expressFormat: true, // Use the default Express/morgan request formatting, with the same colors. Enabling this will override any msg and colorStatus if true. Will only output colors on transports with colorize set to true colorStatus: true, // Color the status code, using the Express/morgan color palette (default green, 3XX cyan, 4XX yellow, 5XX red). Will not be recognized if expressFormat is true ignoreRoute: function (req, res) { return false; } // optional: allows to skip some log messages based on request and/or response })); 

El código aceptado anteriormente tiene problemas con ES6. Usa el siguiente código

 function logReqRes(req, res, next) { const oldWrite = res.write; const oldEnd = res.end; const chunks = []; res.write = (...restArgs) => { chunks.push(new Buffer(restArgs[0])); oldWrite.apply(res, restArgs); }; res.end = (...restArgs) => { if (restArgs[0]) { chunks.push(new Buffer(restArgs[0])); } const body = Buffer.concat(chunks).toString('utf8'); console.log({ time: new Date().toUTCString(), fromIP: req.headers['x-forwarded-for'] || req.connection.remoteAddress, method: req.method, originalUri: req.originalUrl, uri: req.url, requestData: req.body, responseData: body, referer: req.headers.referer || '', ua: req.headers['user-agent'] }); // console.log(body); oldEnd.apply(res, restArgs); }; next(); } module.exports = logReqRes; 

Encontré que la solución más simple a este problema era agregar una propiedad del body al objeto res al enviar la respuesta, a la que posteriormente puede acceder el registrador. Agrego esto a mi propio espacio de nombres que mantengo en los objetos de req y res para evitar nombrar colisiones. p.ej

 res[MY_NAMESPACE].body = ... 

Tengo un método de utilidad que formatea todas las respuestas a mi respuesta API / JSON estandarizada, por lo que al agregar esta línea expuso el cuerpo de respuesta cuando el inicio de sesión se desencadena por onFinished evento de onFinished .