Midmare - HTTP-Layer free Node.js module

Midmare is a minimalistic open source library. I wrote it in a fairly short time in order to optimize specific processes in my company. But as a result, it was possible to come to a solution, the potential of which significantly exceeds the original idea.



In this article I will talk about the features and capabilities of Midmare , as well as share my experience in creating your own library.



Background



The product I am working with is currently undergoing a migration process. Until it is over, we exist in parallel on two platforms and move away from legacy. I am doing a web application backend for a new platform. Some processes have to be constantly unified with other teams.



Taking these features into account, it was necessary to find a flexible and universal solution to rewrite the existing backend. This solution was the Midmare library.



Introductory tasks



I had a task to make it so that the library can be used with both TypeScript and JavaScript. At the same time, the team aimed to completely rewrite the code from TS to JS to speed up development.



JS is not typed, so development is much faster with it, albeit less stable. We were willing to take such risks as we planned to protect ourselves by writing enough tests.



At first, for a week and a half, I thought about the concept, went through different options. Until I came to the idea that it would be cool to use a functional approach so that it would be possible to insert any link in any chain of execution without consequences.



I came up with the idea to use middleware



Namely - to make a chain of intermediate processing functions that are executed one after the other and react to each other's errors (errors, problems, data changes, etc.).



So I got a stack of middleware, which is similar in principle to Koa. This similarity ensures that the rest of the library is easy to use. But in Midmare there are significantly fewer methods, only 4. The Midmare library itself is minimalistic.



Beginning of work



Before installing Midmare, you need to download and install Node.js version 10 or higher. When creating a new project, you also need to create package.json with the npm init command first .



Installing Midmare is done via the npm install midmare command .



Below is a sample application initialization.





General Application Initialization on Midmare Using Routers





(Router-Level Middleware)



Midmare features



First and foremost, we're talking about the impressive code decomposition capabilities. Intermediate functions (middleware) may not know anything about each other. They just take data, process it and release it further.



The Midmare library is ideal when you need to use the same routing system for different APIs - source and destination. That is, when you need to create a certain common processing node. But you can also create simpler applications.



Here are some examples to highlight the capabilities of Midmare.





Catching errors using an intermediate function. He is also an example of code decomposition





A simple intermediate function that closes an HTTP session in case of route mismatch





An example of processing a command, in this case, sending data to Redis



The small library does its little job, but it doesn't limit the options available to you in any way. In Midmare, you can connect virtually anything - without puzzling over how to build an architecture.



Key advantage



The key advantage of this library is complete isolation from any layers (HTTP, WS, etc.). If Koa is designed for an HTTP server, then Midmare does not create restrictions in this regard.



You can even just write a terminal utility. With Midmare, this is convenient since we can use parameters in path. As in the example below:







Using Midmare, you can go back to the same HTTP server. It will not be difficult to connect it. There is already a ready-made router for HTTP .



With this, you can also safely connect WebSockets. You just need to initialize the WebSockets client itself. And then it's up to the most simple routing.





Example of Combining HTTP and WebSockets with Midmare



This versatility eliminates the need to think through different ways to solve the same problem in one program.



In fact, it is rather difficult to list all the possibilities of implementation, because without restrictions any idea can be applied to the library.



I have not seen ready-made libraries of this format



That is, a complete analogue: without low-level bindings, whether it be WebSockets, HTTP, or, more generally, network communication or software work in the OS itself.



Midmare can do it all at the same time and literally in 5-6 lines of tuning.



And the idea behind it is quite simple - to build a chain of execution of functions using the next / send method to call. If nothing further needs to be called, the program will stop. Plus routing, minus HTTP - and we have Midmare.



Why use this library?



You can always write your own solution. Of course, in this case, your decomposition or the code itself may be lame (for example, you may not be able to wedge in between steps in the chain). If there are many such flaws, then a program written by hand can come to a bad ending in a year or two. Midmare avoids this.



Besides, there are too many filters in the world of programmers. Someone wants to write in TypeScript, someone in JS. I was looking for a solution to capture both options.





Now I try to actively test and refine Midmare.



A big plus of a small library is that its creator actively supports it.



I test my library every day and, accordingly, quickly find pitfalls or flaws. With a small library, any problem can be fixed in no time.



Cyclic calls are the first of the fixed issues



Let's look at the example below:







Let's say we need to add a '/ send' call to the .process ('/ message') step, but .process ('/ send') already contains a '/ message' call. Then Step # 2 will call Step # 1. At the same time, in Step # 1, the call to Step # 2 will be triggered each time - and so on in a circle.



When you work on creating a library, you need to catch such problems, show them to users, explain what it is fraught with.



In this case, we will get the Maximum call stack size exceeded error and the JS will fall in response to multiple recursive calls to the same function.



The solution to this problem in this library is: Keeping path history in one context. That is, each call to `ctx.send` or ʻapp.send` has its own call history.



Since Midmare has a handle on this point, the library will throw an error if called in a loop.



There may be a situation in which a circular call is needed. For example, two intermediate functions handle the same data differently because there is a possibility of breaking out of the loop. That is, when one of the functions contains an if-else, which will work in the else and ignore the cyclic call.



In case the implementation requires cycling, Midmare has an option to set the error to ignore via ʻignoreCycleError: true`.







The library is waiting for its community



In principle, it makes no sense to add anything to such a pure library. It would be nice to add the ability to connect plugins, but with middleware this can be solved without new functionality.



If in a particular case some processing is missing, you can add it yourself to conditional 4 lines. As in the example with the function for closing the HTTP session:







All additional processing can be moved to a separate repository. Or to distribute routers to repositories. Everything will be connected and processed the same way.



What the library really would do well for now is a community that would build its own tools from the library. Therefore, I invite the community to contribute to the development of the library. Join and test.



Author:Ivan Petushinsky, Senior Node.js Developer



All Articles