Make a Typescript Middleware Engine

Photo by Anders Jildén on Unsplash

Introduction

The Middleware pattern is prevalent, especially in the NodeJS ecosystem — and for a good reason! It gives your users a simple interface for extending your software to fit their particular use case and decoupling the sender and receiver, among many other benefits. If you’ve spent any time working with Node’s HTTP/HTTPS libraries, express, KOA, or just about every Node-based web server, then you’ve seen the pattern before.

Today, we’ll dig in and learn more about the middleware pattern by building our very own middleware engine, Typescript edition! In the sections that follow, I’m going to start with code, then offer some explanations into the how and why. Ready? Here we go!

Typing

We’ll start with the types that I made to handle the engine. For the most part, they show how the different elements of our engine are going to work.

Our Typings for the middleware engine

First, I started by defining the type for the next function. It’s invoked at the end of every middleware module. The Next is essentially a container. In particular, it’s a container for functions. A crucial fact for later!

The middleware module comes next. The main part of the framework. Each middleware encapsulates work to be executed on our context object before executing the next function, as shown in the first example.

Finally, we have the definition for the actual engine, the pipe. It has two functions, use and execute. Use loads the pipe with middleware, while execute runs through all of the middleware in the pipe, using the context object.

The Code

Instead of using a class, we will use the revealing module pattern to share our public API. First, we need to declare the stack, an array that will hold all of our middleware functions.

This portion of the code is pretty straight forward. First, we declare our pipeline, the middleware engine, that optionally takes a comma-separated middleware list on instantiation. Next, the stack is defined, then use as a constant. Use takes in a list of middleware and adds them to the stack. Pushing it onto the end.

Next is where the magic happens, the execute function. It’s powered by two key components: a recursive algorithm and closure.

First, on line 2, we declare our index at -1 since 0 acts as the first index of our stack array. Next, we set up our recursive function, handler. We do some basic error checking first to make sure each middleware is only being called once. Then, if the middleware index matches the length of the stack, return the context.

On line 21, We select a middleware function from the stack based on the current index and run it. Note how along with context, we pass the handler function to next. This means that when next() is called in the middleware function, it’s actually invoking another run of the handler function, at index +1. A notice how context is actually defined as an exec's argument, and we pass it around to our inner functions? That’s closure! When a variable is defined in an outer scope and referenced within a nested function.

Finally, on lines 27 and 28, we kick off the recursive handler and wait for it to return with a value. That value is then passed back to the rest of your program.

Now let’s look at the whole module at once!

At the end of the function (line 63), we return use and execute, offering them as our public API. Now let’s see this engine at work!

I hope you enjoyed my little demo here. If you’d like to see the entire project, it’s available on my GitHub!

Thanks for reading!

--

--

--

Illustrator, Designer & Web Developer — I’m a creative of many different hats. Currently residing in the absolutely beautiful Pacific Northwest.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

A modern way of AJAX in WordPress using REST API

Angular 13. What’s new

HashMap: Map vs Object in JavaScript

BLoc Pattern in Flutter explained with Real Example

Unity and Android — Connecting the dots

https://mylead.global/ref/447780

https://sites.google.com/view/youtub-courses1-tube-digital-/home

Interview Questions for a Front-End Developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Lem Canady

Lem Canady

Illustrator, Designer & Web Developer — I’m a creative of many different hats. Currently residing in the absolutely beautiful Pacific Northwest.

More from Medium

7 Reasons to run React JS for speed boosting in software development vs Angular JS

Dependency Injection in JS

Firefly Semantics Slice Entity Store Active API Guide

Loading Javascript Asynchronously (Defer vs Async)