Skip to content

Instantly share code, notes, and snippets.

@rjkip
Created November 16, 2014 15:55
Show Gist options
  • Save rjkip/8cd620d815b7b6d324de to your computer and use it in GitHub Desktop.
Save rjkip/8cd620d815b7b6d324de to your computer and use it in GitHub Desktop.
HTTP server using Recoil
<?php
use React\EventLoop\LoopInterface;
use React\Http\Request;
use React\Http\Response;
use Recoil\Coroutine\CoroutineInterface;
use Recoil\Coroutine\CoroutineProviderInterface;
use Recoil\Coroutine\CoroutineTrait;
use Recoil\Kernel\Strand\StrandInterface;
use Recoil\Recoil;
require_once __DIR__ . '/../vendor/autoload.php';
Recoil::run('main');
function main()
{
yield Recoil::execute(httpServer());
}
function httpServer()
{
$loop = (yield Recoil::eventLoop());
$server = Server::listen($loop, 8080);
while (true) {
/** @var Transaction $transaction */
$transaction = (yield $server);
$transaction->response->writeHead(200, ['Content-Type' => 'text/plain']);
$transaction->response->end(sprintf('%s: %s', $transaction->request->getPath(), date_create()->format('r')));
}
}
class Server implements CoroutineProviderInterface
{
/**
* @var CoroutineInterface
*/
private $coroutine;
public static function listen(LoopInterface $loop, $port, $hostname = '127.0.0.1')
{
$server = new self;
$server->coroutine = new EventCoroutine();
$socketServer = new \React\Socket\Server($loop);
$socketServer->listen($port, $hostname);
$httpServer = new \React\Http\Server($socketServer);
$httpServer->on('request', $server->coroutine->transform([Transaction::class, 'fromEvent']));
return $server;
}
public function coroutine(StrandInterface $strand)
{
return $this->coroutine;
}
}
class Transaction
{
/**
* @var Request
*/
public $request;
/**
* @var Response
*/
public $response;
/**
* @param Request $request
* @param Response $response
* @return Transaction
*/
public static function fromEvent(Request $request, Response $response)
{
$transaction = new self;
$transaction->request = $request;
$transaction->response = $response;
return $transaction;
}
}
class EventCoroutine implements CoroutineInterface
{
use CoroutineTrait;
/**
* @var StrandInterface
*/
private $calledStrand;
public function call(StrandInterface $strand)
{
$this->calledStrand = $strand;
$strand->suspend();
}
/**
* @param callable $eventDataTransformer
* @return callable
*/
public function transform(callable $eventDataTransformer)
{
return function () use ($eventDataTransformer) {
$this->calledStrand->resumeWithValue(call_user_func_array($eventDataTransformer, func_get_args()));
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment