DEV Community

Cover image for NodeJS + Express part 3: Middleware
Eric The Coder
Eric The Coder

Posted on • Edited on

NodeJS + Express part 3: Middleware

Here is a series of articles that will allow you to create backend applications with NodeJS + Express.

This series is the continuation of my series on the basics of NodeJS. If you don't have basic knowledge of NodeJS read this series first: Introduction to NodeJS

Node.js is today a must, so it is essential for a developer to master it.

So I will publish a new article about every two days and little by little you will learn everything there is to know about Node.js + Espress

To not miss anything follow me on twitter: https://twitter.com/EricTheCoder_


Middleware

Middleware are functions that execute during the request to the server. Those functions have access to the request and response parameters so can perform many things to enhance/automate API functionalities

The middleware sit in between the request and response

user request -> midlleware -> response
Enter fullscreen mode Exit fullscreen mode

Create your first Middleware

Let's assume we want a function to log the url address of the request every time a page is visit.

Without middleware we could have done this with code like that:

app.get('/about', (req, res) => {
    console.log(req.url)
    console.log(req.params)
    console.log(req.query)
    return res.send('About Page')
})
Enter fullscreen mode Exit fullscreen mode

That will work just fine but what if we have 100 different routes? We cannot copy/paste those console.log() lines to every routes.

One solution is to put those logs in middleware function

const logger  = (req, res, next) => {
    console.log(req.url)
    console.log(req.params)
    console.log(req.query)
    next()
}
Enter fullscreen mode Exit fullscreen mode

That's a pretty simple function. You are already familiar with the req and res parameters. The new thing here is the next() function. The next() function is a Espress pre-define function that give back the control to the calling routes. After executing the console.log() the request need to continue is road to the calling route.

Here is a full exemple of a middleware

const logger  = (req, res, next) => {
    console.log(req.url)
    console.log(req.params)
    console.log(req.query)
    next()
}

app.use(logger) // execute your middleware for all requests

app.get('/about', (req, res) => {
    return res.send('About Page')
})
Enter fullscreen mode Exit fullscreen mode

When the user visit /about Express will execute the app.get(). But just before, it will execute the middleware specified in the app.use(). Once the middleware is executed the next() will continue the app.get() execution

Here is the sequence of execution:

client request → /about ⇒ logger() → app.get() → client response

When creating a middleware you are not force to use the next(). You can send your own response and override/omit the app.get() completely

const logger  = (req, res, next) => {
    console.log(req.url)
    console.log(req.params)
    console.log(req.query)
    res.send('Custom About page')
}
Enter fullscreen mode Exit fullscreen mode

Here is the sequence of execution:

client request → /about ⇒ logger() → client response

If the middleware only apply to one or two route you can use this syntaxe to execute the middleware only for those routes

const logger  = (req, res, next) => {
    console.log(req.url)
    console.log(req.params)
    console.log(req.query)
    next()
}

app.get('/about', logger, (req, res) => {
    return res.send('About Page')
})
Enter fullscreen mode Exit fullscreen mode

Noted we did not use the app.use() but only specified a middleware function as a parameter of the app.get()

You can also execute your middleware only for request that are under a specific path ex: /api

app.use('/api', logger)
Enter fullscreen mode Exit fullscreen mode

Multiple middleware can be use

app.use([logger, auth])
Enter fullscreen mode Exit fullscreen mode

Noted the middleware will be executed in the same order as declare.

Middleware can change the request object

const auth  = (req, res, next) => {
    const user = req.query.user
    if (user === 'admin') {
        req.user = ( name: 'admin', id: 1 }
        next()
    } else {
        res.status(401).send('Unauthorized')
    }
}
Enter fullscreen mode Exit fullscreen mode

In the last exemple we add a user object to the request. That user object can now be use in the routes.

app.use(auth)

app.get('/about', (req, res) => {
    console.log(req.user)
    return res.send('About Page')
})
Enter fullscreen mode Exit fullscreen mode

This exemple as been ultra simplified but it show the real power of middleware

Conclusion

That's all for today, follow me on twitter: https://twitter.com/EricTheCoder_ to be notified of the publication of the next article (within two days).

Top comments (2)

Collapse
 
olsard profile image
olsard

Thanks for good examples and explanation.

Collapse
 
khantnyar profile image
Khant Si Thu Phyo

Nice articles
can I learn microservices with nodejs ?
start from scratch