2013-10-06 9 views
29

Tytuł powinien być dość samoobjawny.Jednostka rejestrująca ekspresowe rejestrowanie danych

Dla celów debugowania, chciałbym wyrazić, aby wydrukować kod odpowiedzi i treść dla każdego obsługiwanego żądania. Drukowanie kodu odpowiedzi jest łatwe, ale drukowanie treści odpowiedzi jest trudniejsze, ponieważ wydaje się, że treść odpowiedzi nie jest łatwo dostępna jako właściwość.

Następujące nie działa:

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

Oczywiście, mógłbym z łatwością drukować odpowiedzi na kliencie, który emitowany wniosek, ale wolałbym robić po stronie serwera zbyt.

PS: Jeśli to pomaga, wszystkie moje odpowiedzi są fałszywe, ale mam nadzieję, że istnieje rozwiązanie, które działa z ogólnymi odpowiedziami.

Odpowiedz

40

Nie jesteś pewien, czy to najprostsze rozwiązanie, ale możesz napisać oprogramowanie pośrednie, aby przechwycić dane zapisane w odpowiedzi. Upewnij się, że wyłączyłeś 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

Dzięki @ laurent-perrin. Twoja odpowiedź na pewno działa. Będę czekać, aby sprawdzić, czy ktoś ma prostsze rozwiązanie, w przeciwnym razie oznaczę to jako zaakceptowaną odpowiedź. –

+0

Ładne rozwiązanie, ale co, jeśli muszę użyć kompresji odpowiedzi? – marmor

+0

powinien działać, tak długo jak nazywasz 'app.use' przed oprogramowaniem pośredniczącym kompresji. –

6

Można użyć express-winston i skonfigurować przy użyciu:

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

przykład w 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

znalazłem najprostsze rozwiązanie tego problemu było dodać obiekt body do OZE obiekt podczas wysyłania odpowiedzi, który później może uzyskać dostęp do rejestratora. Dodaję to do mojej własnej przestrzeni nazw, którą utrzymuję na obiektach req i res, aby uniknąć nazwania kolizji. na przykład

res[MY_NAMESPACE].body = ... 

Mam metodę narzędziowy, który formatuje wszystkie odpowiedzi na moje odpowiedzi standaryzowanego API/JSON, więc dodanie tej jednej wkładki nie ujawnił treść odpowiedzi, gdy rejestrowanie zostaje wywołany przez onFinished przypadku res.

4

Wpadłem na problem, stosując podejście zaproponowane przez Laurenta. Czasami porcja jest ciągiem znaków i dlatego powoduje problemy w wywołaniu funkcji Buffer.concat(). W każdym razie, znalazłem drobną modyfikację naprawiono rzeczy:

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

Po prostu zdałem sobie sprawę, że zrobiłem to w bardzo krótkim czasie. Ale usunął kod, ponieważ drukował tablicę bajtów. Powinienem był przekonwertować go na ciąg. :( –