bittyphp / middleware
PSR-15 HTTP Middleware implementation.
This package has no released version yet, and little information is available.
README
Bitty comes with a PSR-15 middleware implementation.
Installation
It's best to install using Composer.
$ composer require bittyphp/middleware
Official Middleware
Bitty only comes with middleware for the most basic of needs. However, using the MiddlewareInterface
you can build support for almost anything you can think of.
- Router
- Security (Work in Progress)
- Error Handler (Work in Progress)
Basic Usage
To use Bitty's middleware outside of Bitty the setup is fairly straightforward. The details of each call will be explained later.
<?php use Bitty\Middleware\MiddlewareChain; // Create a middleware chain. $middleware = new MiddlewareChain(); // Optional: Override the default handler. $middleware->setDefaultHandler(...); // Optional: Add your custom middleware. $middleware->add(...); $middleware->add(...); $middleware->add(...); // Process the request. $response = $middleware->handle($request);
Default Handler
The default handler is what gets called when nothing else processes the request. It must be an instance of Psr\Http\Server\RequestHandlerInterface
. By default, this is just a class that returns a 404 Not Found response. You can override the default handler to be anything you want, but you don't have to.
For more information, see the section on Creating a Request Handler.
<?php use Bitty\Middleware\MiddlewareChain; use Psr\Http\Server\RequestHandlerInterface; /** @var RequestHandlerInterface */ $defaultHandler = ...; $middleware = new MiddlewareChain($defaultHandler);
You can also set the default handler after the middleware chain has been constructed.
<?php use Bitty\Middleware\MiddlewareChain; use Psr\Http\Server\RequestHandlerInterface; /** @var RequestHandlerInterface */ $defaultHandler = ...; $middleware = new MiddlewareChain(); $middleware->setDefaultHandler($defaultHandler);
Adding Middleware
All middleware added must implement Psr\Http\Server\MiddlewareInterface
. The middleware chain is built using a first-in, first-out approach. This means the first middleware you add will be the first middleware that gets called. You can use this to structure your middleware in the order you want.
For more information, see the section on Creating Middleware.
<?php use Bitty\Middleware\MiddlewareChain; use Psr\Http\Server\MiddlewareInterface; $middleware = new MiddlewareChain(); /** @var MiddlewareInterface */ $someMiddleware = ...; $middleware->add($someMiddleware);
Processing the Request
The final step is processing the request. The middleware chain will handle any request that implements Psr\Http\Message\ServerRequestInterface
. This should produce a Psr\Http\Message\ResponseInterface
which you can then send to the user.
<?php use Bitty\Middleware\MiddlewareChain; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; $middleware = new MiddlewareChain(); /** @var ServerRequestInterface */ $request = ...; /** @var ResponseInterface */ $response = $middleware->handle($request);
Creating a Request Handler
If you'd like to do more than return a simple 404 Not Found response in the event that no middleware processed a request, you'll have to build a custom request handler. You can use this to return an error page, redirect the user to a search page, or display a help page. A request handler can be any class that implements Psr\Http\Server\RequestHandlerInterface
.
<?php use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; class SomeHandler implements RequestHandlerInterface { public function handle(ServerRequestInterface $request): ResponseInterface { /** @var ResponseInterface */ $response = ...; return $response; } }
Then you simply set your handler as the default handler for the middleware chain.
<?php $defaultHandler = new SomeHandler(); $middleware = new MiddlewareChain($defaultHandler);
Creating Middleware
There are two basic approaches to creating a middleware component:
- Pre-process middleware
- Post-process middleware
Pre-process Middleware
This middleware style intercepts all requests and has the ability to prevent further middleware from being called. It can also be used to modify the request before passing it along to the next handler. A security layer might use this style of middleware, as it can determine if a user is authorized to perform an action and stop the request from continuing if needed.
<?php use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; class SomeMiddleware implements MiddlewareInterface { public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { if (/* able to process request */) { /** @var ResponseInterface */ $response = ...; return $response; } // You can modify the request before passing it along $newRequest = $request->withHeader('X-Validated', 'true'); // if unable to handle request, call the next middleware handler return $handler->handle($newRequest); } }
Post-process Middleware
Alternatively, you can use a post-process middleware that allows all other middleware to be called and then it can intercept the response before it's returned to the user. Something like this might be used for an API to always add a JSON content type if the request was to an API resource.
<?php use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; class SomeMiddleware implements MiddlewareInterface { public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { /** @var ResponseInterface */ $response = $handler->handle($request); if (/* request meets criteria */) { return $response->withHeader('Content-type', 'application/json'); } return $response; } }