DEV Community

loading...
Cover image for HTTP Middleware in a nutshell

HTTP Middleware in a nutshell

dakujem profile image Andrej Rypo ・3 min read

I wanted to point people to a simple and framework-agnostic explanation of middleware. I found none. I wrote one.

What it looks like

The basic structure of an HTTP middleware implementation:

function middleware(Request $request, callable $next): Response {

    // 1. Code that happens before the next middleware is invoked.
    // Note: this code may alter the Request

    // 2. Invoke the next middleware.
    // Note: this step is optional too
    $response = $next($request);

    // 3. Code that happens after the next middleware returns.
    // Note: this code may alter the Response

    return $response ;
}
Enter fullscreen mode Exit fullscreen mode

At its core, an HTTP middleware is a piece of code that returns a Response.

How it works

We can see from the code snippet, that each middleware is a wrapper around the next middleware.

An execution pipeline is composed by adding layers of such decoupled wrappers, usually around an app kernel.

Middleware
Layers of HTTP middleware, borrowed from Slim Framework

Each middleware receives a Request and a reference to the next middleware in the pipeline (also called a handler).

A middleware can do 3 optional things:

  1. alter the Request (by injecting meta information for the rest of the app or pre-processing resources)
  2. delegate the execution to the next handler passing it the (altered) Request
  3. alter the Response returned by the next handler, or produce a completely new Response

πŸ’‘
A middleware may choose not to invoke the next handler and terminate the pipeline. For example, this happens in an authorization middleware if a request is not authorized.

Finally, the pipeline is executed using a middleware dispatcher.
There is quite a number of dispatchers available and several frameworks ship with their own.

What it is for

Middleware provides a means to decompose a complex solution into smaller self-contained pieces of code.
The app kernel (controllers and such) can focus on business logic and avoid being bloated by authorization, authentication, CORS, caching, routing and other concerns that can be moved to HTTP middleware.

PSR-15

PSR-15 is a standard that defines two interfaces:

According to this standard, a middleware from the first snippet would look like this:

class Middleware implements MiddlewareInterface
{
    public function process(
        ServerRequestInterface $request,
        RequestHandlerInterface $next
    ): ResponseInterface
    {

        // 1. Code that happens before the next middleware is invoked.
        // Note: this code may alter the Request

        // 2. Invoke the next middleware.
        // Note: this step is optional too
        $response = $next->handle($request);

        // 3. Code that happens after the next middleware returns.
        // Note: this code may alter the Response

        return $response ;
    }
}
Enter fullscreen mode Exit fullscreen mode

The Request and Response interfaces come from the PSR-7 standard.

To make it compatible with the first snippet which represents a functional middleware, we can simply implement the __invoke magic method:

Code of the '__invoke' method
    public function __invoke(
        ServerRequestInterface $request,
        callable $next
    ): ResponseInterface {
        $handler = new class($next) implements RequestHandlerInterface {
            private $next;

            public function __construct(callable $next)
            {
                $this->next = $next;
            }

            public function handle(
                ServerRequestInterface $request
            ): ResponseInterface
            {
                return ($this->next)($request);
            }

        };
        return $this->process($request, $handler);
    }
Enter fullscreen mode Exit fullscreen mode

You can look up PSR-15 compatible middleware and dispatchers.

Conclusion

We have seen that middleware is just a self-contained piece of code that returns a Response.
We can compose layers of middleware to create an app.

Here are some resources to dig deeper:

πŸ‘‹

There are also other explanations of middleware, with different meanings in different contexts. This one refers to HTTP request handling pipeline.

Discussion

pic
Editor guide