node.jsexpresshttpmorgan

How to get the request body in morgan() middleware?


I am learning how to work with middlewares and there is a task to post a JSON resource by using morgan() middleware. But when I write a code for posting something, I cannot get the body of the morgan.

const express = require('express');
const morgan = require('morgan');
const app = express();
app.use(morgan('tiny'));

const generateId = () => {
    const randNum = Math.floor(Math.random() * 5000)
    return randNum;
}

const isExist = (arr, name) => {
    const found = arr.find(arrItem => arrItem.name === name) ? true : false
    return found;
}
app.post('/api/persons', (req, res) => {
    const body = req.body
    if (!body.name || !body.number) {
        return res.status(400).json({
            error: "missing data"
        })
    } else if (isExist(notes, body.name) === true) {
        return res.status(400).json({
            error: "existed data"
        })
    }
    const note = {
        id: generateId(),
        name: body.name,
        number: body.number
    }
    notes = notes.concat(note)

    res.json(note)
})
const PORT = 3001;
app.listen(PORT, () => {
    console.log(`Server is worling on ${PORT}`)
})

Then I found morgan-body and used it and it worked.

// ...
const morganBody = require('morgan-body')
const bodyParser = require('body-parser')

app.use(bodyParser.json())
morganBody(app)

app.post('/api/persons', (req, res) => {
    // the same code as the above
}
//...

But now, the task is to change the log in the console like this I am a little bit uncomfortable with using 2 middlewares in 1 backend (don’t know if that’s ok). That’s why I faced problems with the potential solutions for this situation:

  1. How to get morgan()'s request body (both in the format of the log and in js code) in order to get rid of morgan-body and write my custom tokens?
  2. How to write custom tokens (could not find any documentation about this) for morgan-body to get rid of morgan()?

Because I am a beginner it would be helpful to hear which option is more preferable and why is it. If any additional info would be needed or something is wrong with my question feel free to point it out. Thank you in advance.


Solution

  • First of all, you can have as much middleware as you want, and for large applications, they tend to have a lot of middleware.

    To create a custom token for morgan, you can do something like:

    morgan.token('body', req => {
      return JSON.stringify(req.body)
    })
    
    app.use(morgan(':method :url :body'))
    

    This should works fine if req.body has been set, but by default it's not. You have to use body-parsing middleware to populate it.

    So before you use morgan middleware you have to put some body parser:

    app.use(express.json())
    app.use(morgan(':method :url :body'))
    

    Note: express.json is a built-in middleware function in Express. See more here.