symfony/http-kernel
The Symfony HttpKernel component converts a Request into a Response through a structured process built on the EventDispatcher, and is flexible enough to power full-stack frameworks, micro-frameworks, or advanced CMS systems like Drupal.
Minimal steps
Install or update the component:
composer require symfony/http-kernel
composer update symfony/http-kernel
Laravel already ships this component. If you are on the 5.4 LTS line, upgrade to v5.4.54+ to receive the latest security fixes; use the equivalent patch for your Symfony version.
Core concepts
HttpKernelInterface turns a Request into a Response through a structured pipeline.HttpKernelInterface, Request, Response, EventDispatcher, HttpKernel.App\Http\Kernel extends Illuminate\Foundation\Http\Kernel and implements Symfony’s HttpKernelInterface; it does not extend Symfony’s Kernel.First use case
use Illuminate\Http\Request;
use Illuminate\Contracts\Http\Kernel;
$request = Request::capture();
$response = app(Kernel::class)->handle($request);
$response->send();
Where to look first
app/Http/Kernel.php and Illuminate\Foundation\Http\Kernel.vendor/symfony/http-kernel/.Request handling pipeline
$response = app(\Illuminate\Foundation\Http\Kernel::class)->handle(
$request,
\Symfony\Component\HttpKernel\HttpKernelInterface::MAIN_REQUEST,
true // catch exceptions
);
MAIN_REQUEST runs the full HTTP lifecycle.SUB_REQUEST is used for fragments and internal dispatches.Middleware integration
Laravel uses its own middleware pipeline, not Symfony’s MiddlewareInterface:
// app/Http/Kernel.php
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
// ...
];
Use middleware for cross-cutting request/response concerns; use kernel events when you need to hook the Symfony-level lifecycle.
Event-driven extensions
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\RequestEvent;
$dispatcher->addListener(KernelEvents::REQUEST, function (RequestEvent $event) {
$request = $event->getRequest();
// inspect or modify the request
});
Register listeners in a service provider or a package boot method.
Sub-requests for fragments
$subRequest = $request->duplicate(null, null, ['_route' => 'partial.route']);
$fragment = app(\Illuminate\Foundation\Http\Kernel::class)->handle(
$subRequest,
\Symfony\Component\HttpKernel\HttpKernelInterface::SUB_REQUEST
);
HttpCache
use Symfony\Component\HttpKernel\HttpCache\HttpCache;
$cache = new HttpCache($kernel, $cacheDir);
$response = $cache->handle($request);
After v5.4.54, cache-internal headers are stripped from backend responses; do not rely on those headers surviving the cache layer.
Integration tips
HttpKernelBrowser for lightweight kernel-level tests:
use Symfony\Component\HttpKernel\HttpKernelBrowser;
$client = new HttpKernelBrowser($kernel);
$client->request('GET', '/');
HttpCache in long-running or worker environments, ensure the cache directory is shared and writable.Pitfalls
Security release v5.4.54
UriSigner, profiler token handling, session ID reuse, HttpCache header stripping, and unserialize hardening.HttpCache internal headers
UriSigner hash parameter
TypeError when the hash parameter is not a string. Still validate signed URL input; do not assume query parameters have the expected type.Profiler token validation
Session ID reuse in long-running processes
Unserialize hardening
CacheWarmerAggregate, LoggerDataCollector, and HttpCache store now use allowed_classes => false when unserializing. If you store custom objects in those areas, verify the data still round-trips correctly.Locale handling
HEAD requests
HEAD. Do not assume GET-only checks cover HEAD.Enum and argument handling
ValueError explicitly.Debugging tips
$dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
\Log::error('Kernel exception', [
'exception' => $event->getThrowable(),
'request' => $event->getRequest()->query->all(),
]);
});
KernelInterface::VERSION over deprecated constants.Extension points
Custom event listeners
$dispatcher->addListener(KernelEvents::FINISH_REQUEST, function ($event) {
$event->getResponse()->headers->set('X-Custom-Header', 'value');
});
Override kernel bootstrapping
public function boot()
{
parent::boot();
// custom boot logic
}
Modify request/response globally
$dispatcher->addListener(KernelEvents::REQUEST, function ($event) {
$event->setRequest($event->getRequest()->withHeader('X-Processed', 'true'));
});
Handle exceptions
$dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
if ($event->getThrowable() instanceof \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface) {
return;
}
$event->setResponse(new \Symfony\Component\HttpFoundation\Response('Custom error', 500));
});
Sub-request caching
$cache = new HttpCache($kernel, $cacheDir);
$fragment = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
Keep cache-internal concerns isolated from application code; after v5.4.54 those headers are stripped from backend responses.
How can I help you explore Laravel packages today?