More tests, misc fixes

This commit is contained in:
Chris 2024-03-13 01:28:14 +01:00
parent 7953ce51ee
commit b730b82ef7
7 changed files with 106 additions and 12 deletions

View File

@ -8,6 +8,10 @@ class Configuration
{ {
private array $config = []; private array $config = [];
public function __construct(array $config=[])
{
$this->config = $config;
}
public static function createDefault(): Configuration public static function createDefault(): Configuration
{ {

View File

@ -11,6 +11,7 @@ use React\EventLoop\Loop;
use React\EventLoop\LoopInterface; use React\EventLoop\LoopInterface;
use React\Socket\SecureServer; use React\Socket\SecureServer;
use React\Socket\SocketServer; use React\Socket\SocketServer;
use React\Socket\TcpServer;
class Daemon class Daemon
{ {
@ -20,10 +21,11 @@ class Daemon
private Server $server; private Server $server;
private LoggerInterface $logger; private Logger $logger;
public function __construct(Configuration $config, bool $verbose=false, ?LoopInterface $loop=null) public function __construct(Configuration $config, bool $verbose=false, ?LoopInterface $loop=null)
{ {
if (!defined("MERCUREACT_VERSION")) define("MERCUREACT_VERSION", "0.0.0");
$this->config = $config; $this->config = $config;
$this->loop = $loop??Loop::get(); $this->loop = $loop??Loop::get();
$this->logger = $this->createLogger($verbose); $this->logger = $this->createLogger($verbose);
@ -42,7 +44,7 @@ class Daemon
{ {
$this->server = new Server($this->config, $this->logger, $this->loop); $this->server = new Server($this->config, $this->logger, $this->loop);
$this->logger->info("NoccyLabs Mercureact Daemon v".MERCUREACT_VERSION); $this->logger->info("Starting NoccyLabs Mercureact Daemon v".MERCUREACT_VERSION." (".MERCUREACT_BUILDTIME.")");
$listenAddress = $this->config->getListenAddress(); $listenAddress = $this->config->getListenAddress();
if (!$listenAddress) { if (!$listenAddress) {
@ -53,16 +55,19 @@ class Daemon
$certificate = $this->config->get("server.encryption.local_cert"); $certificate = $this->config->get("server.encryption.local_cert");
if ($certificate) { if ($certificate) {
$this->logger->warning("SSL/TLS suport is broken.");
$this->logger->info("Using local cert: {$certificate}"); $this->logger->info("Using local cert: {$certificate}");
$context = [ $context = $this->config->get("server.encryption.");
'tls' => $this->config->get("server.encryption.")
];
$uri = 'tls://' . $listenAddress; $uri = 'tls://' . $listenAddress;
$context['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_3_SERVER;
$socket = new TcpServer($listenAddress);
$socket = new SecureServer($socket, null, $context??[]);
} else { } else {
$uri = 'tcp://' . $listenAddress; $uri = 'tcp://' . $listenAddress;
$context = [];
$socket = new SocketServer($uri);
} }
$socket = new SocketServer($uri, $context??[]);
$this->server->listen($socket); $this->server->listen($socket);
} }

View File

@ -32,6 +32,11 @@ class ApiHandler
return new Promise( return new Promise(
function (callable $resolve, callable $reject) use ($next, $request) { function (callable $resolve, callable $reject) use ($next, $request) {
if (!$this->config->get('server.enable_api', true)) {
$resolve($next($request));
return;
}
$path = $request->getUri()->getPath(); $path = $request->getUri()->getPath();
// FIXME remove this when done debugging // FIXME remove this when done debugging

View File

@ -75,11 +75,14 @@ class ResponseMiddleware
'method' => $request->getMethod(), 'method' => $request->getMethod(),
'path' => $request->getUri()->getPath(), 'path' => $request->getUri()->getPath(),
]); ]);
return $response return $response
// ->withAddedHeader('Link', '<https://'.$host.'/.well-known/mercure>; rel="mercure"') // ->withAddedHeader('Link', '<https://'.$host.'/.well-known/mercure>; rel="mercure"')
// ->withAddedHeader('Link', '<wss://'.$host.'/.well-known/mercure>; rel="mercure+ws"') // ->withAddedHeader('Link', '<wss://'.$host.'/.well-known/mercure>; rel="mercure+ws"')
->withHeader('Access-Control-Allow-Origin', '*') ->withHeader('Access-Control-Allow-Origin',
->withHeader('Content-Security-Policy', "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'") $this->config->get('server.cors.allow_origin', '*'))
->withHeader('Content-Security-Policy',
$this->config->get('server.cors.csp', "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'"))
->withHeader('Cache-Control', 'must-revalidate') ->withHeader('Cache-Control', 'must-revalidate')
->withHeader('Server', 'Mercureact/0.1.0'); ->withHeader('Server', 'Mercureact/0.1.0');
} }

View File

@ -32,7 +32,7 @@ class Server
private SplObjectStorage $webSocketClients; private SplObjectStorage $webSocketClients;
private TopicManager $topicManager; private TopicManager $topicManager;
private Logger $logger; private Logger $logger;
private ResponseMiddleware $responseMiddleware; private ResponseMiddleware $responseMiddleware;
@ -47,13 +47,13 @@ class Server
* *
* *
*/ */
public function __construct(Configuration $config, ?LoggerInterface $logger, ?LoopInterface $loop=null) public function __construct(Configuration $config, ?Logger $logger, ?LoopInterface $loop=null)
{ {
$this->loop = $loop??Loop::get(); $this->loop = $loop??Loop::get();
$this->config = $config; $this->config = $config;
$this->logger = $logger ?? new NullLogger(); $this->logger = $logger ?? new Logger("main");
if ($logger instanceof Logger) { if ($logger instanceof Logger) {
$topicLogger = $logger->withName("broker"); $topicLogger = $logger->withName("broker");
} else { } else {
@ -89,7 +89,7 @@ class Server
* @return HttpServer * @return HttpServer
*/ */
private function createHttpServer(): HttpServer private function createHttpServer(): HttpServer
{ {
$stack = [ $stack = [
$this->responseMiddleware = new ResponseMiddleware( $this->responseMiddleware = new ResponseMiddleware(
config: $this->config, config: $this->config,

View File

@ -0,0 +1,48 @@
<?php
namespace NoccyLabs\Mercureact;
use PHPUnit\Framework\Attributes\CoversClass;
#[CoversClass(Configuration::class)]
class ConfigurationTest extends \PHPUnit\Framework\TestCase
{
public function testCreatingDefaultConfiguration()
{
$config = Configuration::createDefault();
$this->assertInstanceOf(Configuration::class, $config);
}
public function testGettingSingleValues()
{
$config = new Configuration([
'foo.bar' => 'baz',
'foo.baz' => true,
'foo.bin' => 42,
]);
$this->assertEquals('baz', $config->get("foo.bar"));
$this->assertEquals(true, $config->get("foo.baz"));
$this->assertEquals(42, $config->get("foo.bin"));
}
public function testGettingMultipleValues()
{
$config = new Configuration([
'foo.bar' => 'baz',
'foo.baz' => true,
'foo.bin' => 42,
'bar' => false,
]);
$this->assertEquals([
'foo.bar' => 'baz',
'foo.baz' => true,
'foo.bin' => 42,
], $config->get("foo."));
$this->assertEquals(false, $config->get("bar"));
$this->assertEquals([], $config->get("bar."));
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace NoccyLabs\Mercureact\Http\Middleware;
use PHPUnit\Framework\Attributes\CoversClass;
use Psr\Http\Message\ResponseInterface;
use React\Http\Message\ServerRequest;
use React\Promise\Promise;
#[CoversClass(NotFoundHandler::class)]
class NotFoundHandlerTest extends \PHPUnit\Framework\TestCase
{
public function testAlwaysResolvesTo404Response()
{
$handler = new NotFoundHandler();
$request = new ServerRequest("GET", "/");
$result = null;
$promise = $handler->__invoke($request)->then(function ($r) use (&$result) {
$result = $r;
});
$this->assertInstanceOf(ResponseInterface::class, $result);
/** @var ResponseInterface $result */
$this->assertEquals(404, $result->getStatusCode());
}
}