Created
November 8, 2016 15:02
-
-
Save lisachenko/825e1042b7152c3fc32f655b7e818e8f to your computer and use it in GitHub Desktop.
Swoole FCGI server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Protocol\FCGI; | |
use Protocol\FCGI\FrameParser; | |
use Protocol\FCGI\Record\BeginRequest; | |
use Protocol\FCGI\Record\EndRequest; | |
use Protocol\FCGI\Record\Params; | |
use Protocol\FCGI\Record\Stdin; | |
use Protocol\FCGI\Record\Stdout; | |
include __DIR__ . '/vendor/autoload.php'; | |
class FCGIRequest | |
{ | |
public $id = null; | |
public $role = 0; | |
public $flags = 0; | |
public $params = []; | |
public $stdin = ''; | |
} | |
class FCGIServer extends swoole_server | |
{ | |
/** | |
* List of requests | |
* | |
* @var array|FCGIRequest[] | |
*/ | |
private $requests = []; | |
public function __construct($host, $port) | |
{ | |
parent::__construct($host, $port); | |
$this->on('connect', (new ReflectionMethod($this, 'onConnect'))->getClosure($this)); | |
$this->on('close', (new ReflectionMethod($this, 'onClose'))->getClosure($this)); | |
$this->on('receive', (new ReflectionMethod($this, 'onReceive'))->getClosure($this)); | |
} | |
protected function onConnect($server, $id) | |
{ | |
$this->requests[$id] = new FCGIRequest(); | |
} | |
protected function onReceive($server, $id, $fromId, $data) | |
{ | |
while (FrameParser::hasFrame($data)) { | |
$message = FrameParser::parseFrame($data); | |
if ($message instanceof BeginRequest) { | |
$this->requests[$id]->id = $message->getRequestId(); | |
$this->requests[$id]->role = $message->getRole(); | |
$this->requests[$id]->flags = $message->getFlags(); | |
} | |
if ($message instanceof Params) { | |
$this->requests[$id]->params += $message->getValues(); | |
} | |
if ($message instanceof Stdin) { | |
$isLastParam = $message->getContentLength() == 0; | |
if (!$isLastParam) { | |
$this->requests[$id]->stdin .= $message->getContentData(); | |
} else { | |
$this->onRequest($id); | |
} | |
} | |
} | |
} | |
protected function onRequest($id) | |
{ | |
$request = $this->requests[$id]; | |
$body = print_r($request, true); // let's response with content of all FCGI params from the request | |
$bodySize = strlen($body); | |
/** @var FCGI\Record[] $messages */ | |
$messages = [ | |
// we can also split responses into several chunks for streaming large response | |
new Stdout("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: {$bodySize}\r\n\r\n{$body}"), | |
new Stdout(''), // empty one, according to the specification | |
new EndRequest(FCGI::REQUEST_COMPLETE, $appStatus = 0), // normal request termination | |
]; | |
$responseContent = ''; | |
foreach ($messages as $message) { | |
$message->setRequestId($request->id); | |
$responseContent .= $message; | |
} | |
$this->send($id, $responseContent); | |
$this->close($id); | |
} | |
protected function onClose($server, $id) | |
{ | |
unset($this->requests[$id]); | |
} | |
} | |
$server = new FCGIServer("127.0.0.1", 9501); | |
$server->start(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment