lighthouse / middleware
PSR-15 HTTP Middleware Pipeline for the Lighthouse framework
Installs: 11
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/lighthouse/middleware
Requires
- php: ^8.2
- psr/http-message: ^2.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- lighthouse/http: ^0.1
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^11.0
README
A PSR-15 HTTP Middleware Pipeline for the Lighthouse framework.
Installation
composer require lighthouse/middleware
Requirements
- PHP 8.2 or higher
Features
- PSR-15 compliant middleware pipeline
- Onion-style middleware processing
- Callable middleware support
- Request/response modification
- Short-circuit capability
Quick Start
Basic Pipeline
use Lighthouse\Middleware\Pipeline; use Lighthouse\Middleware\CallableMiddleware; use Psr\Http\Server\RequestHandlerInterface; $pipeline = new Pipeline(); // Add middleware $pipeline->pipe(new LoggingMiddleware()); $pipeline->pipe(new AuthenticationMiddleware()); $pipeline->pipe(new RoutingMiddleware()); // Process request $response = $pipeline->handle($request);
Callable Middleware
You can use closures instead of full middleware classes:
$pipeline->pipe(function ($request, $handler) { // Before: modify request $request = $request->withAttribute('start_time', microtime(true)); // Call next middleware $response = $handler->handle($request); // After: modify response return $response->withHeader('X-Request-Time', microtime(true) - $request->getAttribute('start_time')); });
Middleware Order (Onion Model)
Middleware is processed in order added, but responses flow back in reverse:
$pipeline->pipe($middleware1); // Executes first, returns last $pipeline->pipe($middleware2); // Executes second, returns second-to-last $pipeline->pipe($middleware3); // Executes last, returns first // Request flow: middleware1 → middleware2 → middleware3 → handler // Response flow: middleware1 ← middleware2 ← middleware3 ← handler
Short-Circuiting
Middleware can return early without calling the next handler:
$pipeline->pipe(function ($request, $handler) { if (!$this->isAuthenticated($request)) { // Return immediately, skip remaining middleware return new Response(401); } return $handler->handle($request); });
Fallback Handler
Set a handler to use when no middleware generates a response:
use Lighthouse\Middleware\FallbackHandler; // Throw exception (default) $pipeline = new Pipeline(); // Return 404 response $pipeline = new Pipeline(new FallbackHandler( fn() => new Response(404, body: 'Not Found') )); // Or set later $pipeline->fallback($customHandler);
Add Multiple Middleware
$pipeline->through([ new CorsMiddleware(), new AuthMiddleware(), new RateLimitMiddleware(), ]);
Creating Middleware
Implement MiddlewareInterface:
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; class TimingMiddleware implements MiddlewareInterface { public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ): ResponseInterface { $start = microtime(true); $response = $handler->handle($request); $duration = microtime(true) - $start; return $response->withHeader('X-Response-Time', sprintf('%.3fms', $duration * 1000)); } }
API Reference
Pipeline
| Method | Description |
|---|---|
pipe(MiddlewareInterface|callable $middleware) |
Add middleware to pipeline |
through(array $middleware) |
Add multiple middleware |
fallback(RequestHandlerInterface $handler) |
Set fallback handler |
handle(ServerRequestInterface $request) |
Process request through pipeline |
getMiddleware() |
Get middleware stack |
clear() |
Remove all middleware |
CallableMiddleware
Wraps a callable as MiddlewareInterface:
$middleware = new CallableMiddleware( fn($request, $handler) => $handler->handle($request) );
NextHandler
Wraps a callable as RequestHandlerInterface:
$handler = new NextHandler( fn($request) => new Response(200) );
FallbackHandler
Default handler when middleware stack is exhausted:
// Throws RuntimeException $handler = new FallbackHandler(); // Returns custom response $handler = new FallbackHandler(fn() => new Response(404));
Testing
composer test
License
MIT License. See LICENSE for details.
Part of the Lighthouse Framework
This package is part of the Lighthouse Framework, an educational PHP framework designed to teach how modern frameworks work internally.