Logging requests and responses in express middleware

10,669

Solution 1

You need an event listener that will be triggered when response.end (or send) methods are called. Express doesn't have such listener but node.js raw api does have.

There is a finish event in node.js http server instances which makes you able to do things after you sent your response to the client.

You can easily integrate with your existing Express server:

response.on('finish', () => {
  // Do your logging here.
});

I recommend that save your logs in a javascript object during request and send them inside of finish event's callback when response has sent.

Solution 2

I found an existing module, morgan-body that accomplishes what you're trying to do.

Here's how you'd use the middleware, per the documentation:

const morganBody = require('morgan-body');
const bodyParser = require('body-parser');
const express = require("express");

const app = express();

// must parse body before morganBody as body will be logged
app.use(bodyParser.json());

// hook morganBody to express app (Unlike typical express middleware you're passing the actual app into the function)
morganBody(app);

This answer could be useful if you want to use an out of the box solution or are looking for some reference points on how to implement it yourself.

Share:
10,669
Maikel Ruiz
Author by

Maikel Ruiz

Building cloud applications in Javascript and Python

Updated on June 14, 2022

Comments

  • Maikel Ruiz
    Maikel Ruiz almost 2 years

    I'm trying to implement a logger in an Express application. I need it to be able to log requests and the response (status code and body) sent back for each request. I started writing a middleware that looks like this:

    function (req, res, next) {
        ...
        res.on('finish', function () {
           Logger.debug('For request', req);
           Logger.debug('Response sent');
        });
        ...
    }
    

    I need to access the data passed to the res object method used to send the response. For example, if in one controller I had:

    res.json({ foo: 'bar' })
    

    I need a way to get that { foo: 'bar' } object, something like this maybe:

    function (req, res, next) {
        ...
        res.on('finish', function () {
           Logger.debug('For request', req);
           var data = res.data; // or res.body, or whatever
           Logger.debug('Response: ' + res.statusCode, data);
        });
        ...
    }
    

    Is there any property or method in the Express res object that I could use for that? Or, is there a better strategy for logging requests and the responses for them?

  • Natan Lotério
    Natan Lotério about 3 years
    this is just ugly. It could work. But is still a non-pattern
  • lazzy_ms
    lazzy_ms about 3 years
    I tried this to add as middleware to log the request but the request got stuck.