Middleware Functions
Tags: node, javascript, express, middleware
Published: 2021-12-06 08:13:01

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](https://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'})
})
```
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})
})

...
```
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()
}
```
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'))
...
```
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.