Installation Add the package to your Laravel project via Composer:
composer require drift/http-kernel
Register the service provider in config/app.php under providers:
Drift\HttpKernel\KernelServiceProvider::class,
Basic Setup
Replace Laravel’s default Kernel class with Drift\HttpKernel by extending Drift\HttpKernel\Kernel in app/Http/Kernel.php:
use Drift\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel
{
// Override middleware groups, routes, etc.
}
First Async Use Case Wrap a synchronous middleware in an async promise for non-blocking execution:
use Drift\HttpKernel\Middleware\AsyncMiddleware;
use React\Promise\PromiseInterface;
class AsyncExampleMiddleware extends AsyncMiddleware
{
public function handle(Request $request, Closure $next): PromiseInterface
{
return parent::handle($request, $next)
->then(function ($response) {
// Async post-processing
return $response;
});
}
}
Key Files to Explore
config/drift.php: Kernel configuration (async settings, middleware groups).app/Http/Kernel.php: Customize middleware and route handling.vendor/drift/http-kernel/src/: Core classes (e.g., Kernel, AsyncMiddleware).Async Middleware Pipeline
Leverage AsyncMiddleware to chain async operations without blocking the event loop:
// In Kernel.php
protected function middleware(): array
{
return [
\App\Http\Middleware\AsyncExampleMiddleware::class,
// Other middleware...
];
}
Promise-Based Request Handling
Convert synchronous routes to async by wrapping them in Promise:
Route::get('/async', function () {
return \React\Promise\resolve('Async response');
});
Event Loop Integration Use ReactPHP’s event loop for I/O-bound tasks (e.g., database queries, HTTP calls):
use React\EventLoop\Factory;
use React\Promise\Timer\Timeout;
$loop = Factory::create();
$loop->run();
Middleware Groups
Define async-specific middleware groups in Kernel.php:
protected $middlewareGroups = [
'async' => [
\Drift\HttpKernel\Middleware\AsyncMiddleware::class,
// Async-only middleware...
],
];
spatie/async or spatie/laravel-async for hybrid sync/async workflows.react/promise-database for async DB queries with Eloquent.Route::get('/process', function () {
return \React\Promise\resolve()
->then(function () {
// Heavy computation
});
});
Blocking the Event Loop
Avoid synchronous I/O (e.g., file_get_contents, sleep) in async middleware:
// ❌ Blocks the loop
$content = file_get_contents('http://example.com');
// ✅ Async alternative
use React\HttpClient\Client;
$client = new Client();
$promise = $client->get('http://example.com')->then(...);
Middleware Order Matters Async middleware must be placed before synchronous middleware to avoid deadlocks:
// Correct order
protected $middleware = [
\App\Http\Middleware\AsyncAuth::class, // Async first
\App\Http\Middleware\VerifyCsrfToken::class, // Sync second
];
Promise Rejection Handling Always handle rejected promises to prevent uncaught exceptions:
$promise->then(function ($response) {
// Success
})->otherwise(function (\Throwable $e) {
// Log or rethrow
\Log::error($e);
throw $e;
});
Configuration Quirks
config/drift.php has async set to true:
'async' => env('APP_ASYNC', false),
AppServiceProvider booting if using async bootstrapping.React\Promise\Timer\Timeout to log promise states:
$promise->then(function () {
\Log::debug('Promise resolved');
})->otherwise(function () {
\Log::debug('Promise rejected');
});
$loop->addPeriodicTimer(1, function () {
\Log::debug('Loop active tasks:', $loop->getPendingTimers());
});
React\Promise\Deferred for manual promise testing:
$deferred = new \React\Promise\Deferred();
$promise = $deferred->promise();
// Simulate async resolution
$deferred->resolve('test');
Custom Async Middleware
Extend Drift\HttpKernel\Middleware\AsyncMiddleware to add async logic:
class RateLimitMiddleware extends AsyncMiddleware
{
public function handle(Request $request, Closure $next): PromiseInterface
{
return \React\Promise\resolve()
->then(function () use ($request) {
// Async rate limiting logic
})->then($next);
}
}
Override Kernel Methods
Customize Drift\HttpKernel\Kernel methods like terminate() for async cleanup:
public function terminate($request, $response)
{
parent::terminate($request, $response);
// Async post-termination tasks
}
ReactPHP Integration
Use React\Promise\Timer\Timeout for async timeouts:
use React\Promise\Timer\Timeout;
$timeout = new Timeout($loop, 5.0); // 5-second timeout
$promise = $timeout->promise();
Hybrid Sync/Async Routes Mix sync and async routes by conditionally wrapping handlers:
Route::get('/hybrid', function () {
if ($shouldBeAsync) {
return \React\Promise\resolve('Async response');
}
return response()->json(['sync' => true]);
});
How can I help you explore Laravel packages today?