mercureact/src/Http/Server.php

134 lines
3.7 KiB
PHP
Raw Normal View History

2024-03-10 02:06:19 +00:00
<?php
namespace NoccyLabs\Mercureact\Http;
2024-03-11 00:20:45 +00:00
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
2024-03-10 02:06:19 +00:00
use NoccyLabs\Mercureact\Broker\TopicManager;
use NoccyLabs\Mercureact\Configuration;
2024-03-10 19:22:28 +00:00
use NoccyLabs\Mercureact\Http\Middleware\ApiHandler;
use NoccyLabs\Mercureact\Http\Middleware\MercureHandler;
use NoccyLabs\Mercureact\Http\Middleware\NotFoundHandler;
use NoccyLabs\Mercureact\Http\Middleware\ResponseMiddleware;
use NoccyLabs\Mercureact\Http\Middleware\SecurityMiddleware;
use NoccyLabs\Mercureact\Http\Middleware\WebSocketHandler;
2024-03-11 00:20:45 +00:00
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
2024-03-10 02:06:19 +00:00
use React\EventLoop\Loop;
use React\EventLoop\LoopInterface;
use React\Http\HttpServer;
use React\Http\Middleware\LimitConcurrentRequestsMiddleware;
use React\Http\Middleware\RequestBodyBufferMiddleware;
use React\Socket\SecureServer;
2024-03-10 02:06:19 +00:00
use React\Socket\ServerInterface;
use SplObjectStorage;
class Server
{
private Configuration $config;
private LoopInterface $loop;
private ?HttpServer $server = null;
2024-03-10 02:06:19 +00:00
private SplObjectStorage $webSocketClients;
private TopicManager $topicManager;
2024-03-13 00:28:14 +00:00
2024-03-11 13:39:58 +00:00
private Logger $logger;
2024-03-11 00:20:45 +00:00
2024-03-10 02:06:19 +00:00
/**
*
*
*/
2024-03-13 00:28:14 +00:00
public function __construct(Configuration $config, ?Logger $logger, ?LoopInterface $loop=null)
2024-03-10 02:06:19 +00:00
{
$this->loop = $loop??Loop::get();
$this->config = $config;
2024-03-13 00:28:14 +00:00
$this->logger = $logger ?? new Logger("main");
2024-03-12 01:21:42 +00:00
if ($logger instanceof Logger) {
$topicLogger = $logger->withName("broker");
} else {
$topicLogger = $this->logger;
}
2024-03-11 00:20:45 +00:00
2024-03-12 01:21:42 +00:00
$this->topicManager = new TopicManager($topicLogger);
2024-03-11 00:40:05 +00:00
$this->loop->addPeriodicTimer(30, function () {
$this->topicManager->garbageCollect();
});
2024-03-10 02:06:19 +00:00
$this->webSocketClients = new SplObjectStorage();
}
/**
*
*
* @return void
*/
public function listen(ServerInterface $socket): void
{
if (!$this->server) {
$this->server = $this->createHttpServer();
}
2024-03-10 02:06:19 +00:00
$this->server->listen($socket);
$this->logger->info(sprintf(
"Listening on %s",
strtr($socket->getAddress(), [ "tcp://"=>"http://", "tls://"=>"https://"])
));
2024-03-11 00:20:45 +00:00
}
2024-03-10 02:06:19 +00:00
/**
*
* @return HttpServer
*/
2024-03-10 23:50:15 +00:00
private function createHttpServer(): HttpServer
2024-03-13 00:28:14 +00:00
{
$stack = [];
$maxConcurrent = $this->config->get("server.limits.max_concurrent", 100);
$maxRequestBody = $this->config->get("server.limits.max_request_body", 102400);
$stack[] = new LimitConcurrentRequestsMiddleware($maxConcurrent);
$stack[] = new RequestBodyBufferMiddleware($maxRequestBody);
$stack[] = new ResponseMiddleware(
config: $this->config,
logger: $this->logger->withName("http"),
);
$stack[] = new SecurityMiddleware(
config: $this->config
);
if ($this->config->getEnableWebSockets()) {
$stack[] = $webSocketHandler = new WebSocketHandler(
config: $this->config,
webSocketClients: $this->webSocketClients,
topicManager: $this->topicManager
);
$this->logger->warning("The WebSocket support is incomplete and insecure, but enabling it as requested.");
}
$stack[] = new MercureHandler(
config: $this->config,
topicManager: $this->topicManager
);
if ($this->config->get('server.enable_api', true)) {
$stack[] = new ApiHandler(
2024-03-10 19:22:28 +00:00
config: $this->config,
topicManager: $this->topicManager
);
$this->logger->info("Enabling the API middleware");
}
$stack[] = new NotFoundHandler();
return new HttpServer(...$stack);
2024-03-10 02:06:19 +00:00
}
}