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 Copyexport 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 Copyimport axios from "axios";
const axiosGithub = axios.create();
axiosGithub.interceptors.request.use(requestInterceptor, errorInterceptor);
axiosGithub.interceptors.response.use(responseInterceptor, errorInterceptor);
Express Application-level middleware
TypeScript Copyfunction 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 Copyconst 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 Copyapp.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 engineeringJavascript
Python
🍩
Framework