Middleware
Introduction
Middleware filters HTTP requests entering your application. Common uses:
- Authentication
- Logging
- CORS headers
- Rate limiting
How Middleware Works
Middleware wraps around your application like layers of an onion:
Request → Middleware A → Middleware B → Controller → Response
↓ ↓ ↓
(before) (before) (handle)
↑ ↑ │
(after) (after) ←───────┘Each middleware can:
- Modify the request before passing it on
- Modify the response after receiving it
- Short-circuit and return early
Creating Middleware
Implement MiddlewareInterface:
php
<?php
namespace App\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class LoggingMiddleware implements MiddlewareInterface
{
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
// Before: Log the request
error_log("Request: {$request->getMethod()} {$request->getUri()}");
// Pass to next middleware/controller
$response = $handler->handle($request);
// After: Log the response
error_log("Response: {$response->getStatusCode()}");
return $response;
}
}Registering Middleware
Add middleware to the application:
php
use App\Middleware\LoggingMiddleware;
use App\Middleware\AuthMiddleware;
$app->pipe(new LoggingMiddleware());
$app->pipe(new AuthMiddleware());Middleware runs in the order registered.
Callable Middleware
Use closures for simple middleware:
php
$app->pipe(function ($request, $handler) {
$response = $handler->handle($request);
return $response->withHeader('X-Powered-By', 'Lighthouse');
});Authentication Example
php
<?php
namespace App\Middleware;
use Lighthouse\Http\Response;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class AuthMiddleware implements MiddlewareInterface
{
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
$token = $request->getHeaderLine('Authorization');
if (!$this->isValid($token)) {
return new Response(401);
}
// Add user to request attributes
$request = $request->withAttribute('user', $this->getUser($token));
return $handler->handle($request);
}
private function isValid(string $token): bool
{
// Validate token...
return $token !== '';
}
private function getUser(string $token): array
{
// Fetch user from token...
return ['id' => 1, 'name' => 'John'];
}
}CORS Example
php
<?php
namespace App\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
class CorsMiddleware implements MiddlewareInterface
{
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
$response = $handler->handle($request);
return $response
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
->withHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
}
}Modifying the Request
Pass data to downstream handlers via attributes:
php
public function process($request, $handler): ResponseInterface
{
$request = $request->withAttribute('startTime', microtime(true));
return $handler->handle($request);
}Access in controllers:
php
$startTime = $request->getAttribute('startTime');