registerRoutes(); } /** * Registers the routes for the server. * * This method is responsible for defining the routes that the server will handle. * It should be implemented in subclasses to provide specific route definitions. * * @return void */ public function registerRoutes(): void { $this->worker = new PSR7Worker( Worker::create(), new Psr17Factory(), new Psr17Factory(), new Psr17Factory() ); $this->router = new Router(); $this->router->get('/', IndexController::class . '::get'); $this->router->post('/', IndexController::class . '::post'); $this->router->get('/healthz', HealthcheckController::class . '::get'); $this->router->group('/.well-known', function (RouteGroup $router) { $router->get('/swagger.yaml', OpenApiController::class . '::get'); $router->get('/swagger.json', OpenApiController::class . '::get'); }); $this->router->middleware(new CorsMiddleware()); $this->router->middleware(new JwtMiddleware()); $this->router->middleware(new ScopeMiddleware()); } /** * Starts the server and handles incoming requests. * * This method enters an infinite loop to continuously handle incoming HTTP requests. * It decodes the request body, routes the request, and sends the response. It also handles * exceptions and ensures proper cleanup after each request. * * @throws \JsonException If there is an error decoding the JSON request body. */ public function startServer(): void { Logger::info(sprintf('Server started: %s', microtime(true))); Logger::info(sprintf('Server PID: %s', getmypid())); Logger::info(sprintf('Server Listening on: 0.0.0.0:%s', Config::get('server.port'))); while (true) { try { $request = $this->worker->waitRequest(); if ($request === null) { break; } $request = $request->withParsedBody(json_decode($request->getBody()->getContents(), true)); $response = $this->router->handle($request); $this->worker->respond($response); } catch (MethodNotAllowedException | NotFoundException) { $uri = ''; if (isset($request)) { $uri = $request->getUri()->getPath(); } $this->worker->respond( JsonResponseFactory::createJsonResponse(new NotFoundResponse($uri)) ); } catch (\Throwable $e) { Logger::error($e->getMessage()); Logger::error($e->getTraceAsString()); $this->worker->respond( JsonResponseFactory::createJsonResponse(new ServerErrorResponse($e)) ); } } } }