withBacklog(102400) ->withReusePort() ->withTcpNoDelay() ) ]; $router = new Router; // Case 1 - JSON $router->addRoute('GET', '/json', new class implements RequestHandler { public function handleRequest(Request $request): Promise { return new Success(new Response(200, [ 'Content-Type' => 'application/json', 'Server' => 'amphp/http-server', ], \json_encode([ 'message' => 'Hello, World!', ]))); } }); // Case 2 - Single Query $router->addRoute('GET', '/db', new class implements RequestHandler { private $mysql; public function __construct() { $config = Amp\Mysql\ConnectionConfig::fromString( 'host='.DB_HOST.' user=benchmarkdbuser password=benchmarkdbpass db=hello_world' ); $this->mysql = Amp\Mysql\pool($config); } public function handleRequest(Request $request): Promise { return new Coroutine($this->doHandleRequest($request)); } private function doHandleRequest($request) { $statement = yield $this->mysql->prepare('SELECT * FROM World WHERE id = ?'); $result = yield $statement->execute([mt_rand(1, 10000)]); if (yield $result->advance()) { $item = $result->getCurrent(); } else { $item = null; } return new Response(200, [ 'Content-Type' => 'application/json', 'Server' => 'amphp/http-server', ], \json_encode($item)); } }); // Case 3 - Multiple Queries $router->addRoute('GET', '/queries', new class implements RequestHandler { private $mysql; public function __construct() { $config = Amp\Mysql\ConnectionConfig::fromString( 'host='.DB_HOST.' user=benchmarkdbuser password=benchmarkdbpass db=hello_world' ); $this->mysql = Amp\Mysql\pool($config); } public function handleRequest(Request $request): Promise { return new Coroutine($this->doHandleRequest($request)); } private function doHandleRequest($request) { $query = $request->getUri()->getQuery(); \parse_str($query, $queryParams); $queries = (int) ($queryParams['queries'] ?? 1); if ($queries < 1) { $queries = 1; } elseif ($queries > 500) { $queries = 500; } $items = []; $statement = yield $this->mysql->prepare('SELECT * FROM World WHERE id = ?'); while ($queries--) { $items[] = new Coroutine($this->execute($statement)); } return new Response(200, [ 'Content-Type' => 'application/json', 'Server' => 'amphp/http-server', ], \json_encode(yield $items)); } private function execute($statement) { $result = yield $statement->execute([mt_rand(1, 10000)]); yield $result->advance(); return $result->getCurrent(); } }); // Case 4 - Fortunes $router->addRoute('GET', '/fortunes', new class implements RequestHandler { private $mysql; public function __construct() { $config = Amp\Mysql\ConnectionConfig::fromString( 'host='.DB_HOST.' user=benchmarkdbuser password=benchmarkdbpass db=hello_world' ); $this->mysql = Amp\Mysql\pool($config); } public function handleRequest(Request $request): Promise { return new Coroutine($this->doHandleRequest($request)); } private function doHandleRequest($request) { $result = yield $this->mysql->query('SELECT * FROM Fortune'); $items = []; while (yield $result->advance()) { $item = $result->getCurrent(); $items[$item['id']] = $item['message']; } $items[0] = 'Additional fortune added at request time.'; \asort($items); \ob_start(); require __DIR__ . '/fortunes.php'; return new Response(200, [ 'Content-Type' => 'text/html; charset=utf-8', 'Server' => 'amphp/http-server', ], \ob_get_clean()); } private function execute($statement) { $result = yield $statement->execute([mt_rand(1, 10000)]); yield $result->advance(); return $result->getCurrent(); } }); // Case 6 - Plaintext $router->addRoute('GET', '/plaintext', new class implements RequestHandler { public function handleRequest(Request $request): Promise { return new Success(new Response(200, [ 'Content-Type' => 'text/plain', 'Server' => 'amphp/http-server', ], 'Hello, World!')); } }); $logger = new Logger('Worker-' . Cluster::getId()); $logger->pushHandler(Cluster::createLogHandler()); $logger->info('Using ' . get_class(Amp\Loop::get())); $options = (new Options) ->withoutCompression() ->withConnectionLimit(102400) ->withConnectionsPerIpLimit(102400); $server = new Server($sockets, $router, $logger, $options); yield $server->start(); Amp\Loop::onSignal(\SIGINT, function (string $watcherId) use ($server) { Amp\Loop::cancel($watcherId); yield $server->stop(); }); });