private function checkValidity(Host $host) { $details = $host->export(); if (!$this->isListeningOn(443, $details["interfaces"])) { throw new \InvalidArgumentException("Host isn't listening on port 443, host not allowed!"); } if (!empty($details["crypto"])) { throw new \InvalidArgumentException("Host must not have crypto settings already!"); } if (empty($details["actions"])) { $this->showActionWarning = true; } }
private static function buildVhost(Host $host, callable $bootLoader) : Vhost { try { $hostExport = $host->export(); $interfaces = $hostExport["interfaces"]; $name = $hostExport["name"]; $actions = $hostExport["actions"]; $middlewares = []; $applications = []; $monitors = []; foreach ($actions as $key => $action) { if ($action instanceof Bootable) { $action = $bootLoader($action); } elseif (is_array($action) && $action[0] instanceof Bootable) { $bootLoader($action[0]); } if ($action instanceof Middleware) { $middlewares[] = [$action, "do"]; } elseif (is_array($action) && $action[0] instanceof Middleware) { $middlewares[] = [$action[0], "do"]; } if ($action instanceof Monitor) { $monitors[get_class($action)][] = $action; } elseif (is_array($action) && $action[0] instanceof Monitor) { $monitors[get_class($action[0])][] = $action[0]; } if (is_callable($action)) { $applications[] = $action; } } if (empty($applications)) { $application = static function (Request $request, Response $response) { $response->end("<html><body><h1>It works!</h1></body></html>"); }; } elseif (count($applications) === 1) { $application = current($applications); } else { // Observe the Server in our stateful multi-responder so if a shutdown triggers // while we're iterating over our coroutines we can send a 503 response. This // obviates the need for applications to pay attention to server state themselves. $application = $bootLoader(new class($applications) implements Bootable, ServerObserver { private $applications; private $isStopping = false; public function __construct(array $applications) { $this->applications = $applications; } public function boot(Server $server, PsrLogger $logger) { $server->attach($this); } public function update(Server $server) : Promise { if ($server->state() === Server::STOPPING) { $this->isStopping = true; } return new Success(); } public function __invoke(Request $request, Response $response) { foreach ($this->applications as $action) { $out = $action($request, $response); if ($out instanceof \Generator) { yield from $out; } if ($response->state() & Response::STARTED) { return; } if ($this->isStopping) { $response->setStatus(HTTP_STATUS["SERVICE_UNAVAILABLE"]); $response->setReason("Server shutting down"); $response->setHeader("Aerys-Generic-Response", "enable"); $response->end(); return; } } } public function __debugInfo() { return ["applications" => $this->applications]; } }); } $vhost = new Vhost($name, $interfaces, $application, $middlewares, $monitors, $hostExport["httpdriver"]); if ($crypto = $hostExport["crypto"]) { $vhost->setCrypto($crypto); } return $vhost; } catch (\Throwable $previousException) { throw new \DomainException("Failed building Vhost instance", $code = 0, $previousException); } }
foreach ($config['plugins'] ?? [] as $pluginClass) { if (!class_exists($pluginClass)) { throw new \LogicException("Plugin class {$pluginClass} does not exist"); } else { if (!is_a($pluginClass, Plugin::class, true)) { throw new \LogicException("Plugin class {$pluginClass} does not implement " . Plugin::class); } } $injector->define(FileKeyValueStorage::class, [':dataFile' => DATA_BASE_DIR . '/keyvalue.%s.json', ':partitionName' => $pluginClass]); $pluginManager->registerPlugin($injector->make($pluginClass)); } $injector->make(PresenceManager::class)->restoreRooms(array_map(function ($room) { return new ChatRoomIdentifier($room['id'], $room['hostname'] ?? 'chat.stackoverflow.com'); }, $config['rooms'])); if ($config['web-api']['enable'] ?? false) { $host = new Host(); $sslEnabled = false; if ($config['web-api']['ssl']['enable']) { if (!isset($config['web-api']['ssl']['cert-path'])) { throw new InvalidConfigurationException('SSL-enabled web API must define a certificate path'); } $sslEnabled = true; $sslCert = realpath($config['web-api']['ssl']['cert-path']); if (!$sslCert) { throw new InvalidConfigurationException('Invalid SSL certificate path'); } $sslKey = null; if (isset($config['web-api']['ssl']['key-path']) && !($sslKey = realpath($config['web-api']['ssl']['key-path']))) { throw new InvalidConfigurationException('Invalid SSL key path'); } $sslContext = $config['web-api']['ssl']['context'] ?? [];