2024-03-10 03:06:19 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace NoccyLabs\Mercureact\Http;
|
|
|
|
|
2024-03-11 01:20:45 +01:00
|
|
|
use Monolog\Handler\StreamHandler;
|
|
|
|
use Monolog\Logger;
|
2024-03-10 03:06:19 +01:00
|
|
|
use NoccyLabs\Mercureact\Broker\TopicManager;
|
|
|
|
use NoccyLabs\Mercureact\Configuration;
|
2024-03-10 20:22:28 +01: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 01:20:45 +01:00
|
|
|
use Psr\Log\LoggerInterface;
|
2024-03-12 01:13:19 +01:00
|
|
|
use Psr\Log\NullLogger;
|
2024-03-10 03:06:19 +01:00
|
|
|
use React\EventLoop\Loop;
|
|
|
|
use React\EventLoop\LoopInterface;
|
|
|
|
use React\Http\HttpServer;
|
2024-03-12 01:13:19 +01:00
|
|
|
use React\Socket\SecureServer;
|
2024-03-10 03:06:19 +01:00
|
|
|
use React\Socket\ServerInterface;
|
|
|
|
use SplObjectStorage;
|
|
|
|
|
|
|
|
class Server
|
|
|
|
{
|
|
|
|
private Configuration $config;
|
|
|
|
|
|
|
|
private LoopInterface $loop;
|
|
|
|
|
|
|
|
private HttpServer $server;
|
|
|
|
|
|
|
|
private SplObjectStorage $webSocketClients;
|
|
|
|
|
|
|
|
private TopicManager $topicManager;
|
2024-03-11 14:39:58 +01:00
|
|
|
|
|
|
|
private Logger $logger;
|
2024-03-11 01:20:45 +01:00
|
|
|
|
2024-03-10 20:22:28 +01:00
|
|
|
private ResponseMiddleware $responseMiddleware;
|
|
|
|
private SecurityMiddleware $securityMiddleware;
|
|
|
|
private WebSocketHandler $webSocketHandler;
|
|
|
|
private MercureHandler $mercureHandler;
|
|
|
|
private ApiHandler $apiRequestHandler;
|
|
|
|
private NotFoundHandler $notFoundHandler;
|
|
|
|
|
2024-03-10 03:06:19 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
2024-03-12 01:13:19 +01:00
|
|
|
public function __construct(Configuration $config, ?LoggerInterface $logger, ?LoopInterface $loop=null)
|
2024-03-10 03:06:19 +01:00
|
|
|
{
|
|
|
|
$this->loop = $loop??Loop::get();
|
|
|
|
|
|
|
|
$this->config = $config;
|
|
|
|
|
2024-03-12 01:13:19 +01:00
|
|
|
$this->logger = $logger ?? new NullLogger();
|
2024-03-12 02:21:42 +01:00
|
|
|
if ($logger instanceof Logger) {
|
|
|
|
$topicLogger = $logger->withName("broker");
|
|
|
|
} else {
|
|
|
|
$topicLogger = $this->logger;
|
|
|
|
}
|
2024-03-11 01:20:45 +01:00
|
|
|
|
2024-03-12 02:21:42 +01:00
|
|
|
$this->topicManager = new TopicManager($topicLogger);
|
2024-03-11 01:40:05 +01:00
|
|
|
$this->loop->addPeriodicTimer(30, function () {
|
|
|
|
$this->topicManager->garbageCollect();
|
|
|
|
});
|
2024-03-10 03:06:19 +01:00
|
|
|
|
|
|
|
$this->webSocketClients = new SplObjectStorage();
|
2024-03-10 20:22:28 +01:00
|
|
|
|
2024-03-11 00:50:15 +01:00
|
|
|
$this->server = $this->createHttpServer();
|
2024-03-10 03:06:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function listen(ServerInterface $socket): void
|
|
|
|
{
|
|
|
|
$this->server->listen($socket);
|
2024-03-12 01:13:19 +01:00
|
|
|
$this->logger->info(sprintf(
|
|
|
|
"Listening on %s",
|
|
|
|
str_replace("tcp://",($socket instanceof SecureServer?"https://":"http://"),$socket->getAddress())
|
|
|
|
));
|
2024-03-11 01:20:45 +01:00
|
|
|
}
|
|
|
|
|
2024-03-10 03:06:19 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @return HttpServer
|
|
|
|
*/
|
2024-03-11 00:50:15 +01:00
|
|
|
private function createHttpServer(): HttpServer
|
2024-03-10 03:06:19 +01:00
|
|
|
{
|
2024-03-12 01:13:19 +01:00
|
|
|
$stack = [
|
2024-03-10 20:22:28 +01:00
|
|
|
$this->responseMiddleware = new ResponseMiddleware(
|
2024-03-11 01:20:45 +01:00
|
|
|
config: $this->config,
|
|
|
|
logger: $this->logger->withName("http"),
|
2024-03-10 20:22:28 +01:00
|
|
|
),
|
|
|
|
$this->securityMiddleware = new SecurityMiddleware(
|
|
|
|
config: $this->config
|
|
|
|
),
|
2024-03-12 01:13:19 +01:00
|
|
|
];
|
|
|
|
if ($this->config->getEnableWebSockets()) {
|
|
|
|
$stack = [ ...$stack,
|
|
|
|
$this->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 = [ ...$stack,
|
2024-03-10 20:22:28 +01:00
|
|
|
$this->mercureHandler = new MercureHandler(
|
2024-03-11 00:50:15 +01:00
|
|
|
config: $this->config,
|
2024-03-10 20:22:28 +01:00
|
|
|
topicManager: $this->topicManager
|
|
|
|
),
|
|
|
|
$this->apiRequestHandler = new ApiHandler(
|
|
|
|
config: $this->config,
|
|
|
|
topicManager: $this->topicManager
|
|
|
|
),
|
|
|
|
$this->notFoundHandler = new NotFoundHandler()
|
2024-03-12 01:13:19 +01:00
|
|
|
];
|
|
|
|
|
|
|
|
return new HttpServer(...$stack);
|
2024-03-10 03:06:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|