api-api, an api for creating apis, coming to a conference near you ... blame amanda for this

2 min read Original article ↗
<?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)); }