2013-10-06 5 views
29

Название должно быть довольно само собой разумеющимся.экспресс-каротаж тела ответа

Для целей отладки я хотел бы выразить, чтобы напечатать код ответа и тело для каждого обслуживаемого запроса. Печать кода ответа достаточно проста, но печать тела ответа сложнее, так как кажется, что тело ответа не доступно в качестве свойства.

Следующая не работает:

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, но, надеюсь, есть решение, которое работает с общими ответами.

ответ

40

Не уверен, что это самое простое решение, но вы можете написать промежуточное программное обеспечение для перехвата данных, записанных в ответ. Убедитесь, что вы отключили 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); 
+0

Thanks @ laurent-perrin. Ваш ответ определенно работает. Я подожду, чтобы увидеть, есть ли у кого-то более простое решение, иначе я буду отмечать его как принятый ответ. –

+0

Хорошее решение, но что, если мне нужно использовать сжатие ответа? – marmor

+0

он должен работать, если вы вызываете 'app.use' перед промежуточным программным обеспечением для сжатия. –

6

Вы можете использовать express-winston и настройки с помощью:

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. E.g. "{{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 
    })); 
0

Я нашел простое решение этой проблемы было добавить body свойство в разрешении объект при отправке ответа, доступ к которому позже может получить регистратор. Я добавляю это в свое собственное пространство имен, которое я поддерживаю на объектах req и res, чтобы избежать коллизий имен. например

res[MY_NAMESPACE].body = ... 

У меня есть метод утилита, которая форматирует все ответы на мой стандартизованный ответ API/JSON, так что добавление этого один вкладыша там подвергается телу ответа при регистрации получает вызвано onFinished случае Рез.

4

Я столкнулся с проблемой, используя подход, предложенный Лораном. Иногда chunk является строкой и поэтому вызывает проблемы при вызове 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); 
+0

Я просто понял, что сделал это как-то очень коротко. Но удалил код, так как он печатал массив байтов. Я должен был преобразовать его в строку. :( –

Смежные вопросы