Summary
- Middleware provides structured protocols to connect applications, streamlining development and enabling efficient connectivity.
- Middleware allows for faster transition of changes and provides easily accessible workplace tools.
- Middleware is a form of modularity that benefits all forms of programming, from high-level to low-level.
You might have heard people use the term "middleware" in various contexts and wondered just what it is they’re talking about. Discover the broad and rich set of technologies and processes that they could be referring to.
Middleware Means Many Things
Middleware is a flexible term that people use to mean different things. In the broadest possible sense, you can think of it as "programs that run in between other programs". In other words, any software that depends on separate code to provide its input and process its output.
Some middleware exists as a full-blown application that transforms data from one state to another, with well-defined protocols and data formats for other code to use. But middleware can also be as granular as a single function, hooking into a series of other functions that a framework runs.
Like a lot of software, middleware takes advantage of the concept of modularity: breaking down a complex process into smaller, more manageable pieces.
How Does Middleware Work?
Middleware is typically as strong as its protocols and publicly-defined behavior. Strict protocols for communication allow programmers to write software that abides by standards to function correctly.
A web application server acts as middleware to connect a user’s front-end experience of a website with the logic and data model that a back-end application and database provide. Since it’s not tightly coupled to the systems that communicate with it, you can—at least, in theory—swap out an app server for a compatible one without having to rewrite application code or restructure your database.
Middleware components often use technologies like JSON, REST, XML, and SOAP. These are all mature, popular, and text-based, which makes it much easier to swap out or reorder components. Their text-based format and wide range of toolsets also enable easier and more reliable debugging.
Different Types of Middleware
Because the term is so broad, there are many different examples of, and uses for, middleware. Some of the most common include:
- Message brokers, which add structure to inter-process communication.
- Web app server and web frameworks.
- Game engines, which provide default behavior that you can use, extend, or replace.
- Event streaming platforms like Apache Kafka.
Using Middleware in Software Development
One of the most tangible uses of middleware is via web frameworks. Most frameworks provide a core environment that you can customize and extend to your own requirements. The model often involves passing HTTP requests through a series of built-in and custom functions, in a defined order, and returning an HTTP response at the end.
The Express.js framework uses this model to support customization. Take this example of a middleware function written in JavaScript:
app.use('/user/:id', (req, res, next) => {
console.log('Request Type:', req.method)
next()
})
The function is simple in the extreme:
- It processes specific URLs beginning "/user/", followed by an id.
- It logs the type of request method which may be a GET, POST, etc.
- It calls a provided function, next, to continue processing the chain of middleware functions.
That final call to next is a vital step in the middleware process and demonstrates how versatile the approach can be. So long as each middleware function behaves independently, you can swap them in and out, and reorder behavior of the whole chain easily.
The PHP framework, Laravel, has an almost identical middleware setup. Notice how the namespace explicitly defines this class as "Middleware".
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureTokenIsValid
{
/**
* Handle an incoming request.
*/
public function handle(Request $request, Closure $next): Response
{
if ($request->input('token') !== 'my-secret-token') {
return redirect('home');
}
return $next($request);
}
}
Again, the role of this particular class is highly specific: all it does is check the request to see if it contains a token. In this case, the middleware function can break the chain, declining to call the next function and, instead, sending a redirect. The redirect function will return an appropriate Response object, which the middleware function should return as part of its signature contract.
This final example shows how Django, a Python-based web framework, handles middleware. Django uses the term "plugin" to describe its middleware architecture, which is similar to other relevant terms you may hear like "hook" or "callback". In essence, it’s simply another case of a middleware setup providing flexibility throughout a structured process.
def simple_middleware(get_response):
# One-time configuration and initialization.
def middleware(request):
# Code to be executed for each request before
# the view (and later middleware) are called.
response = get_response(request)
# Code to be executed for each request/response after
# the view is called.
return response
return middleware
You can then control which middleware runs, and in what order, with a simple array:
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
Django provides default behavior like the CommonMiddleware class which most apps will benefit from; it forbids access to certain "bad" user agents and handles URL normalization. It’s quite common for mission-critical, security-focused middleware to run early on in the pipeline, but this flexibility lets you customize the order depending on the needs of your app.
Why Is Middleware Useful?
Middleware makes it easier to connect applications that weren't designed to be connected. It provides functionality to integrate them, along with robust, structured protocols by which they can communicate.
As a result, middleware has some important benefits, including:
- Streamlined application development and reduced time to market.
- Efficient connectivity.
- Faster transition of changes.
- Easily accessible workplace tools.
Ultimately, middleware is a form of modularity, a concept that is beneficial when applied to all forms of programming, from the highest level right down to the lowest.