georgeff/http-kernel

PSR-15 HTTP kernel. Provides routing, a global middleware stack, per-route middleware, exception handling, and response emission

Maintainers

Package info

github.com/MikeGeorgeff/http-kernel

pkg:composer/georgeff/http-kernel

Statistics

Installs: 9

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-02-22 02:36 UTC

This package is auto-updated.

Last update: 2026-03-22 02:49:31 UTC


README

A PSR-15 HTTP kernel built on top of georgeff/kernel. Provides routing, a global middleware stack, per-route middleware, exception handling, and response emission.

Installation

composer require georgeff/http-kernel

Quick Start

use Georgeff\HttpKernel\HttpKernel;
use Georgeff\Kernel\Environment;

$kernel = new HttpKernel(Environment::Production);

$kernel->addMiddleware(SessionMiddleware::class);

$kernel->addRoute('GET', '/users/{id}', UserHandler::class);

$kernel->withExceptionHandler(function (Throwable $e, ServerRequestInterface $request) {
    $status = $e instanceof HttpExceptionInterface ? $e->getStatusCode() : 500;
    return new JsonResponse([
        'error' => $e->getMessage(),
    ], $status);
});

$kernel->boot();
$kernel->run();

Routing

Routes are registered before boot via addRoute(). The handler can be a RequestHandlerInterface instance or a string service ID resolved from the container.

// Single method
$kernel->addRoute('GET', '/users', ListUsersHandler::class);

// Multiple methods
$kernel->addRoute(['GET', 'POST'], '/users', UsersHandler::class);

Route parameters are available through the matched route object, which is stored as the __route__ request attribute:

$route = $request->getAttribute('__route__');
$id = $route->getArgument('id');

Per-Route Middleware

Routes support their own middleware stack, processed in FIFO order before the route handler:

$route = $kernel->addRoute('GET', '/admin', AdminHandler::class);
$route->addMiddleware(AuthMiddleware::class)
      ->addMiddleware(RoleMiddleware::class);

Middleware

Global middleware is added before boot and runs on every request in FIFO order:

$kernel->addMiddleware(CorsMiddleware::class);
$kernel->addMiddleware($loggingMiddleware);

Middleware can be a MiddlewareInterface instance or a string service ID resolved from the container.

Exception Handling

Register an exception handler to convert exceptions into HTTP responses. Without a handler, exceptions are rethrown. The handler receives the raw Throwable — check instanceof HttpExceptionInterface for HTTP-specific data.

$kernel->withExceptionHandler(function (Throwable $e, ServerRequestInterface $request) {
    $status = $e instanceof HttpExceptionInterface ? $e->getStatusCode() : 500;
    return new JsonResponse([
        'error' => $e->getMessage(),
    ], $status);
});

HTTP Exceptions

The package provides a set of HTTP exception classes:

Class Status
BadRequestHttpException 400
UnauthorizedHttpException 401
ForbiddenHttpException 403
NotFoundHttpException 404
MethodNotAllowedHttpException 405
NotAcceptableHttpException 406
RequestTimeoutHttpException 408
ConflictHttpException 409
GoneHttpException 410
UnsupportedMediaTypeHttpException 415
UnprocessableEntityHttpException 422
TooManyRequestsHttpException 429
InternalServerErrorHttpException 500
BadGatewayHttpException 502
ServiceUnavailableHttpException 503

All extend HttpException and implement HttpExceptionInterface.

MethodNotAllowedHttpException provides getAllowedMethods() and TooManyRequestsHttpException provides getRetryAfter().

Lifecycle Events

The kernel dispatches PSR-14 events at key points in the request lifecycle. Register a Psr\EventDispatcher\EventDispatcherInterface in the container to listen for them:

$kernel->addDefinition(EventDispatcherInterface::class, function () {
    return $myEventDispatcher;
});
Event Dispatched
RequestReceived At the start of handle()
ResponseReady After a response is produced
RequestErrored When an exception is caught in handle()
KernelTerminating During terminate(), after response emission

All events extend Georgeff\Kernel\Event\KernelEvent and carry the kernel instance along with relevant request, response, or exception data as readonly public properties.

Debugging

Enable debug mode to profile the request lifecycle. Pass debug: true to the kernel constructor:

$kernel = new HttpKernel(Environment::Development, debug: true);

When debug mode is enabled, the kernel profiles the following phases:

Phase Description
requestResolution Resolving the ServerRequestInterface from the container
handle Total time spent in handle()
middleware Executing the middleware pipeline
exceptionHandling Running the exception handler (only when an exception occurs)
emission Emitting the response
terminate Running termination logic

The requestResolution, emission, and terminate phases are only recorded when using run(). When calling handle() directly, only handle, middleware, and exceptionHandling (if applicable) are recorded.

Retrieve profiling data via getDebugInfo():

$info = $kernel->getDebugInfo();

// Boot profile from the parent kernel
$info['bootProfile'];

// Request lifecycle profile
$info['requestProfile']['duration'];
$info['requestProfile']['phases']['middleware']['duration'];

Response Helpers

Convenience response classes under Georgeff\HttpKernel\Response:

  • JsonResponse
  • EmptyResponse
  • RedirectResponse

License

MIT