DEV Community

Cover image for Middleware Functions
Semir Teskeredzic
Semir Teskeredzic

Posted on

Middleware Functions

Hello all, in this post I will go through middleware functions, like the one used in NodeJS with ExpressJS. So let's start. Middleware is the code that runs on server between receiving a request and sending a response.

According to expressjs.com:

Middleware functions are functions that have access to the request object (req), the response object (res), and the next function in the application’s request-response cycle. The next function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.

There are several tasks that middleware functions can perform:

  • Execute any code
  • Make changes to the request and response objects
  • End the request-response cycle.
  • Call the next middleware in stack.

One thing that you should always remember is that middleware functions are executed from top to bottom. Which means that when one middleware function ends the cycle the rest of functions will not be executed.

When does middleware function end cycle?

It ends when the middleware function runs but does not invoke next function so it stops after executing.
It also ends the cycle when the response is sent to the browser. So if you have a GET with a route '/', every time someone visits that route, the request is received and the response is sent ending the cycle. All functions that are located below that function won't fire.
It is important to mention that functions with GET POST requests will be executed only when a request from a specified route arrives.

Common usages for Middleware

  • Log of all requests
  • Auth check for protected routes
  • Return 404 pages
  • Parse JSON data from requests
  • Expose folders or files

Examples

404 Pages

In this example we will see how middleware function is used to display 404 page:

...
app.listen(3000)

app.get('/', (req, res) => {
  const homePage = [
    {title: 'Section One', text: 'This is the first section'},
    {title: 'Section Two', text: 'This is the second section'}
  ]
  res.render('index', {title: 'Home', homePage})
})

app.get('/about-us',(req, res) => {
  res.render('about-us', {title: 'This is About us'})
}

app.get('/faq',(req, res) => {
  res.render('faq', {title: 'These are Frequently asked questions'})
}

app.use((req, res) => {
  res.status(404).render('404', {title: '404'})
})
Enter fullscreen mode Exit fullscreen mode

When user arrives to / the response is sent and the cycle is stopped, and if request doesn't match any of the provided then it must be 404 page so we use middleware function with .use to send a response. If we wan't it to be executed when no route is found then it must be at the bottom.

Logging requests

We can log every request by placing a middleware function at the very top of our functions like so:

...
app.listen(3000)

app.use((req, res) => {
  console.log('Request')
  console.log('host: ', req.hostname)
  console.log('path: ', req.path)
  console.log('method: ', req.method)
}

app.get('/', (req, res) => {
  const homePage = [
    {title: 'Section One', text: 'This is the first section'},
    {title: 'Section Two', text: 'This is the second section'}
  ]
  res.render('index', {title: 'Home', homePage})
})

...
Enter fullscreen mode Exit fullscreen mode

When we run the application we will get the log when we visit any route. But it is not working right, currently it will 'freeze' so we won't get any content from any of our routes. This is due to the fact that the middleware function was executed and it stopped the cycle because it didn't invoke the next one. We can fix it by using next(), we will just add it to existing function

...
app.use((req, res, next) => {
  console.log('Request')
  console.log('host: ', req.hostname)
  console.log('path: ', req.path)
  console.log('method: ', req.method)
  next()
}
Enter fullscreen mode Exit fullscreen mode

Now when we run our app, all routes are accessible and we get a log each time request has been received.

Expose Static files

If need to use images, css files, or other assets we won't be able to access it from the browser. We can fix this with middleware function that will expose a folder where all our static files will be located. It is quite simple:

const express = require('express')

const app = express()

app.listen(3000)

app.use(express.static('public'))
...
Enter fullscreen mode Exit fullscreen mode

This is it, we just need to create a public folder in our root directory and put in all files that we need to have accessible by browser. If you do a <link href="/..."> you don't need to include public folder to the path since our code is looking automatically inside the public folder.

Hope you've learned something new and useful.
Thank you for reading, stay safe and have a great day.

Top comments (0)