Routing ReactPHP with Laravel

As previously mentioned, I'm actually playing with asyncronous PHP and I'm trying to combine ReactPHP (which is the most popular framework for this kind of tasks, in PHP) and Laravel (which is the most popular "classic HTTP syncronous" framework).

Today's challenge: run a ReactPHP HTTP Server, but still leveraging the Laravel routing to manage everything with classic and beloved Middlewares, Controllers, and so on.

Here, a simple Laravel command which boots a ReactPHP HTTP Server and routes incoming request to the usual flow of the Laravel's HTTP Kernel.

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

use App;

use Psr\Http\Message\ServerRequestInterface;
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;

use Nyholm\Psr7\Factory\Psr17Factory;
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
use Symfony\Component\HttpFoundation\Response;

class RunServer extends Command
{
  protected $signature = 'run:server';
  protected $description = 'Run asyncronous server';

  public function __construct()
  {
    parent::__construct();
  }

  public function handle()
  {
    $loop = \React\EventLoop\Factory::create();
    $kernel = App::make(\Illuminate\Contracts\Http\Kernel::class);

    $psr17Factory = new Psr17Factory();
    $symfonyHttpFactory = new HttpFoundationFactory();
    $psrHttpFactory = new PsrHttpFactory($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);

    $server = new \React\Http\Server(function (ServerRequestInterface $request) use ($kernel, $symfonyHttpFactory, $psrHttpFactory) {
      /*
        Here, the incoming PSR-7 Request is transformed into a Laravel Request
      */
      $symfonyRequest = $symfonyHttpFactory->createRequest($request);
      $laravelRequest = \Illuminate\Http\Request::createFromBase($symfonyRequest);

      $laravelResponse = $kernel->handle($laravelRequest);

      /*
        Here, the Laravel Response is transformed into a PSR-7 Response
      */
      $response = $psrHttpFactory->createResponse($laravelResponse);

      return $response;
    });

    $socket = new \React\Socket\Server(8080, $loop);
    $server->listen($socket);

    $loop->run();
  }
}

Lot of translations on incoming and outgoing data structures, but thanks to PSR-7 not so many after all.

Show Comments