快递logging响应机构

标题应该是相当自我解释。

为了debugging的目的,我想表示打印每个请求服务的响应代码和正文。 打印响应代码很容易,但是打印响应体更加棘手,因为看起来响应体不容易作为属性提供。

以下不起作用:

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); 

当然,我可以很容易地在发出请求的客户端上打印响应,但我更喜欢在服务器端做。

PS:如果有帮助,我所有的答案都是JSON,但是希望有一个解决scheme可以和一般的答复一起工作。

不知道这是否是最简单的解决scheme,但可以编写一个中间件来拦截写入响应的数据。 确保你禁用了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); 

您可以使用express-winston并使用以下命令进行configuration:

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

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 })); 

我遇到了一个使用Laurentbuild议的方法的问题。 有时chunk是一个string,因此在调用Buffer.concat()时会导致问题。 无论如何,我发现修改了一些细微的东西:

 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); 

我发现这个问题的最简单的解决scheme是在发送响应时向res对象添加一个body属性,这个响应可以被日志logging器访问。 我把这个添加到我自己的命名空间,我维护请求和res对象,以避免命名冲突。 例如

 res[MY_NAMESPACE].body = ... 

我有一个实用的方法,将所有响应的格式设置为标准化的API / JSON响应,所以当日志logging被res的onFinished事件触发时,添加这个内存就暴露了响应主体。