🍽️

Middleware

Middleware is commonly used to implement shared functional requirements in web applications. It is an integral part of web applications, just like libraries, as it helps developers avoid code duplication and encourages separation of concerns.
This guide focuses on middleware used in the context of client and server applications communicating over HTTP, as discussed in this blog post. The author describes middleware as code that wraps around a web application object to do tasks before and/or after the web application is called. These tasks typically include exporting observability data, performing application-wide authentication and authorization, and caching results.

Axios:

Interpreter
TypeScript
export const requestInterceptor = function (requestConfig) {
  requestConfig.startTime = Date.now();
  console.log("url=%s method=%s", requestConfig.url, requestConfig.method);
  return requestConfig;
};

export const responseInterceptor = function (response) {
  console.log(
    "url=%s method=%s status=%s latency=%s",
    response.config.url,
    response.config.method,
    response.status,
    Date.now() - response.config.startTime
  );
  return response;
};

export const errorInterceptor = function (error) {
  if (error.response) {
    console.log(
      "url=%s method=%s error=%s status=%s",
      error.response.config.url,
      error.response.config.method,
      error.response.data,
      error.response.status
    );
  } else if (error.request) {
    console.log(error.request);
  } else {
    console.log("Error", error.message);
  }
  return Promise.reject(error);
};

Usage

TypeScript
import axios from "axios";

const axiosGithub = axios.create();

axiosGithub.interceptors.request.use(requestInterceptor, errorInterceptor);
axiosGithub.interceptors.response.use(responseInterceptor, errorInterceptor);
 

Express

Application-level middleware
TypeScript
function logOriginalUrl (req, res, next) {
  console.log('Request URL:', req.originalUrl)
  next()
}

function logMethod (req, res, next) {
  console.log('Request Type:', req.method)
  next()
}

const logStuff = [logOriginalUrl, logMethod]
app.get('/user/:id', logStuff, (req, res, next) => {
  res.send('User Info')
})
Router-level middleware
TypeScript
const express = require('express')
const app = express()
const router = express.Router()

// a middleware function with no mount path. This code is executed for every request to the router
router.use((req, res, next) => {
  console.log('Time:', Date.now())
  next()
})

// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use('/user/:id', (req, res, next) => {
  console.log('Request URL:', req.originalUrl)
  next()
}, (req, res, next) => {
  console.log('Request Type:', req.method)
  next()
})

// a middleware sub-stack that handles GET requests to the /user/:id path
router.get('/user/:id', (req, res, next) => {
  // if the user ID is 0, skip to the next router
  if (req.params.id === '0') next('route')
  // otherwise pass control to the next middleware function in this stack
  else next()
}, (req, res, next) => {
  // render a regular page
  res.render('regular')
})

// handler for the /user/:id path, which renders a special page
router.get('/user/:id', (req, res, next) => {
  console.log(req.params.id)
  res.render('special')
})

// mount the router on the app
app.use('/', router)
Error-handling middleware
TypeScript
app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

Other resources

Go
  • The book Practical Go by the author, which describes in detail how to implement middleware in client and server applications
  • Github/go-fault, which demonstrates how to use server-side middleware for chaos engineering
Javascript
Python
 
 
🍩
Framework