Skip to content

Instantly share code, notes, and snippets.

@jm42
Created December 23, 2015 13:06
Show Gist options
  • Save jm42/d4b3638343cfa34fb86b to your computer and use it in GitHub Desktop.
Save jm42/d4b3638343cfa34fb86b to your computer and use it in GitHub Desktop.
HTTP Server
<?php
class Request {
public $get;
public $post;
public $server;
function __construct($server, $get, $post) {
$this->get = $get;
$this->post = $post;
$this->server = $server;
}
}
class Response {
public $headers = [];
public $body;
}
<?php
require_once __DIR__ . '/http.php';
require_once __DIR__ . '/server.php';
class App {
function __invoke(Request $req) {
$req = new Response();
$req->body = "\n\n\nHello World\n\n\n";
return $req;
}
}
$app = new App();
if (PHP_SAPI === 'cli') {
$server = new HTTPServer($app);
$server->listen('0.0.0.0', 5400);
$server->start();
}
<?php
class HTTPServer {
private $handler;
private $queue;
function __construct(callable $handler) {
if (!extension_loaded('pcntl')) {
throw new \RuntimeException('pcntl extension required');
}
$queue = '/tmp/aix-queue';
if (file_exists($queue)) {
unlink($queue);
}
touch($queue);
$this->handler = $handler;
$this->queue = msg_get_queue(ftok($queue, 'R'), 0777);
}
function listen($address, $port) {
$pid = pcntl_fork();
sleep(0.001);
if ($pid === -1) {
throw new \RuntimeException('unable to fork');
}
if ($pid > 0) {
return;
}
$lock = '/tmp/aix-' . $address . '-' . $port . '.lock';
if (file_exists($lock)) {
unlink($lock);
}
$cmd = PHP_BINARY . ' -S ' . $address . ':' . $port . ' '
. __DIR__ . DIRECTORY_SEPARATOR . 'server_router.php';
$handler = popen($cmd, 'r');
if ($handler === false) {
throw new \RuntimeException('unable to run PHP cli server');
}
print("Web server listing at http://$address:$port\n");
touch($lock);
while (true) {
if (!file_exists($lock)) {
pclose($handler);
print("Web server closed\n");
exit();
}
sleep(1);
}
}
function start() {
for ($i = 0; $i < 3; $i++) {
$this->runThread(100 + $i);
}
}
function stop() {
for ($i = 0; $i < 3; $i++) {
msg_send($this->queue, 100 + $i, 'exit');
}
}
private function runThread($msgid, $lifetime=10) {
$pid = pcntl_fork();
sleep(0.001);
if ($pid !== 0) {
return;
}
set_time_limit($lifetime);
while (true) {
msg_receive($this->queue, $msgid, $msgtype, 1024*1024, $msg, true);
if ($msg === 'exit') {
exit();
}
list($reqid, $data) = $msg;
$req = new Request($data['server'], $data['get'], $data['post']);
$res = call_user_func($this->handler, $req);
msg_send($this->queue, $reqid, [$res->headers, $res->body], true, true);
unset($msgtype, $msg);
unset($reqid, $data);
unset($req, $res);
gc_collect_cycles();
}
}
}
<?php
session_start();
if (!isset($_SESSION['__msgid'])) {
$_SESSION['__msgid'] = 100 + rand(0, 2);
}
$data = array(
'session_id' => session_id(),
'get' => $_GET,
'post' => $_POST,
'server' => array_merge($_SERVER, $_ENV),
);
session_write_close();
$queue = msg_get_queue(ftok('/tmp/aix-queue', 'R'), 0777);
msg_send($queue, $_SESSION['__msgid'], [$id = rand(), $data], true, false);
msg_receive($queue, $id, $msgtype, 1024*1024, $msg, true);
list($headers, $body) = $msg;
foreach ($headers as $header) {
header($header);
}
print($body);
error_log(sprintf('[%d] %s', http_response_code(), $_SERVER['REQUEST_URI']), 4);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment