|
<?php |
|
|
|
use Symfony\Component\HttpFoundation\Request; |
|
use Symfony\Component\Process\Process; |
|
|
|
require 'vendor/autoload.php'; |
|
|
|
$app = new Silex\Application(); |
|
|
|
$app['debug'] = true; |
|
|
|
$app->get('/', function () { |
|
return <<<HTML |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>API API</title> |
|
</head> |
|
<body> |
|
|
|
<h1>API API</h1> |
|
|
|
<p>This is an API for creating APIs. Just send a |
|
<code>POST</code> request to /api/api with a zip |
|
file attached containing your code under the form |
|
key <code>file</code>.</p> |
|
|
|
<p>We will then run your API!</p> |
|
|
|
</body> |
|
</html> |
|
HTML; |
|
}); |
|
|
|
$app->post('/api/api', function (Request $request) use ($app) { |
|
$appId = hash('sha1', randomBytes(512)); |
|
$appDir = __DIR__.'/tmp/'.$appId; |
|
|
|
if (!$request->files->has('file')) { |
|
return $app->json(['error' => 'missing file'], 412); |
|
} |
|
|
|
if (!is_dir($appDir)) { |
|
mkdir($appDir, 0755, true); |
|
} |
|
|
|
$file = $request->files->get('file'); |
|
$file->move($appDir, '__upload.zip'); |
|
run($appDir, cmd('unzip %s', '__upload.zip')); |
|
run($appDir, cmd('rm %s', '__upload.zip')); |
|
run($appDir, cmd('wget %s', 'https://getcomposer.org/composer.phar')); |
|
run($appDir, cmd('php %s/composer.phar install', $appDir)); |
|
|
|
$port = 8080; |
|
do { |
|
$port++; |
|
$process = run(null, cmd('nc -z 127.0.0.1 %s', $port)); |
|
} while ($process->isSuccessful()); |
|
|
|
background($appDir, cmd('php -S %s app.php', '127.0.0.1:'.$port)); |
|
|
|
return $app->json([ |
|
'id' => $appId, |
|
'port' => $port, |
|
]); |
|
}); |
|
|
|
$app->run(); |
|
|
|
function randomBytes($n) { |
|
$fd = fopen('/dev/urandom', 'r'); |
|
$bytes = fread($fd, $n); |
|
fclose($fd); |
|
return $bytes; |
|
} |
|
|
|
function run($cwd, $cmd) { |
|
$process = new Process($cmd, $cwd); |
|
$process->run(); |
|
|
|
return $process; |
|
} |
|
|
|
function background($cwd, $cmd) { |
|
$client = stream_socket_client('unix://supervisor.ipc', $errno, $errstr); |
|
if (!$client) { |
|
throw new Exception($errstr, $errno); |
|
} |
|
$data = [ |
|
'cmd' => $cmd, |
|
'cwd' => $cwd, |
|
]; |
|
fwrite($client, json_encode($data)); |
|
} |
|
|
|
function cmd($cmd, ...$args) { |
|
return vsprintf($cmd, array_map('escapeshellarg', $args)); |
|
} |