Configuration fixes, makefile tweaks

* The PHAR now gets tagged with version and buildtime
* WebSocket support can now be disabled
This commit is contained in:
Chris 2024-03-12 01:13:19 +01:00
parent da450b510a
commit b3476881e1
7 changed files with 77 additions and 33 deletions

View File

@ -13,6 +13,7 @@ phar: ## Build .phar using pharlite
git clone $(REPODIR) $(BUILDDIR) && \
cd $(BUILDDIR) && \
composer install --no-dev && \
echo "<?php return [ 'version' => '$(shell git describe --tags)', 'buildtime' => '$(shell date)' ];" > src/meta && \
pharlite
mv $(BUILDDIR)/*.phar $(REPODIR) && \
rm -rf $(BUILDDIR)

View File

@ -3,15 +3,25 @@
use NoccyLabs\Mercureact\Configuration;
use NoccyLabs\Mercureact\Daemon;
use PHPUnit\TextUI\Help;
require_once __DIR__."/../vendor/autoload.php";
file_exists(__DIR__."/../vendor") && require_once __DIR__."/../vendor/autoload.php";
file_exists(__DIR__."/../../../autoload.php") && require_once __DIR__."/../../../autoload.php";
if (file_exists(__DIR__."/../src/meta")) {
$meta = require_once(__DIR__."/../src/meta");
define("MERCUREACT_VERSION", $meta['version']??'0.0.0');
define("MERCUREACT_BUILDTIME", $meta['buildtime']);
} else {
define("MERCUREACT_VERSION", "DEV");
define("MERCUREACT_BUILDTIME", null);
}
$opts = getopt("c:C:h");
if (isset($opts['h'])) {
$info = "v".MERCUREACT_VERSION.(MERCUREACT_BUILDTIME?("\nBuilt on ".MERCUREACT_BUILDTIME):"");
fwrite(STDERR, <<<HELP
Mercureact Realtime SSE Daemon
Mercureact Realtime SSE Daemon {$info}
(c) 2024, NoccyLabs - Distributed under GNU GPL v3 or later.
Options:
@ -32,8 +42,9 @@ if (isset($opts['C'])) {
}
file_put_contents($file, <<<DEFAULTS
server:
public_url: https://example.com
address: 0.0.0.0:9000
public_url: https://example.com
websockets: false
cors:
allow_origin: '*'
csp: "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'"
@ -41,9 +52,6 @@ if (isset($opts['C'])) {
cert: foo.pem
key: foo.key
websocket:
enable: true
publish:
overwrite_id: false
reject_duplicates: true

View File

@ -2,3 +2,6 @@
This is alpha quality software. Expect, and please report, any bugs encountered.
## Authentication
When using the query thing for authentication, keep in mind that the authentication details may be saved to logs. `mercureactd` itself doese not log more than the path by default, but any downstream proxies may not be as caring. This is part of the reason why the Mercure specification doesn't care much for WebSockets -- they are hard to secure.

View File

@ -2,7 +2,10 @@
# Please make a copy of me before editing
server:
# Listen address
address: 0.0.0.0:9000
# Enable websocket support (experimental)
websockets: false
# Setup CORS headers
cors:
@ -16,10 +19,6 @@ server:
cert: foo.pem
key: foo.key
# Enable websockets
websocket:
enable: true
publish:
# Assign a UUID to published messages even if one is already set in the message
overwrite_id: false

View File

@ -97,5 +97,16 @@ class Configuration
return $this;
}
public function getEnableWebSockets(): bool
{
return (bool)($this->config['server.websockets']??false);
}
public function setEnableWebSockets(bool $enable): self
{
$this->config['server.websockets'] = $enable;
return $this;
}
}

View File

@ -2,7 +2,10 @@
namespace NoccyLabs\Mercureact;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use NoccyLabs\Mercureact\Http\Server;
use Psr\Log\LoggerInterface;
use React\EventLoop\Loop;
use React\EventLoop\LoopInterface;
use React\Socket\SocketServer;
@ -15,19 +18,33 @@ class Daemon
private Server $server;
private LoggerInterface $logger;
public function __construct(Configuration $config, ?LoopInterface $loop=null)
{
$this->config = $config;
$this->loop = $loop??Loop::get();
$this->logger = $this->createLogger();
}
private function createLogger(): Logger
{
$handlers = [
new StreamHandler(STDOUT)
];
$logger = new Logger("main", $handlers);
return $logger;
}
public function start(): void
{
$this->server = new Server($this->config, $this->loop);
$this->server = new Server($this->config, $this->logger, $this->loop);
$this->logger->info("NoccyLabs Mercureact Daemon v".MERCUREACT_VERSION);
$listenAddress = $this->config->getListenAddress();
if (!$listenAddress) {
fwrite(STDERR, "Warning: Empty listening address. You won't make it far.\n");
$this->logger->warning("Empty listening address. You won't make it far.");
return;
}
$socket = new SocketServer("tcp://".$listenAddress);

View File

@ -13,9 +13,11 @@ use NoccyLabs\Mercureact\Http\Middleware\ResponseMiddleware;
use NoccyLabs\Mercureact\Http\Middleware\SecurityMiddleware;
use NoccyLabs\Mercureact\Http\Middleware\WebSocketHandler;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use React\EventLoop\Loop;
use React\EventLoop\LoopInterface;
use React\Http\HttpServer;
use React\Socket\SecureServer;
use React\Socket\ServerInterface;
use SplObjectStorage;
@ -45,13 +47,13 @@ class Server
*
*
*/
public function __construct(Configuration $config, ?LoopInterface $loop=null)
public function __construct(Configuration $config, ?LoggerInterface $logger, ?LoopInterface $loop=null)
{
$this->loop = $loop??Loop::get();
$this->config = $config;
$this->logger = $this->createLogger();
$this->logger = $logger ?? new NullLogger();
$this->topicManager = new TopicManager();
$this->loop->addPeriodicTimer(30, function () {
@ -70,17 +72,11 @@ class Server
*/
public function listen(ServerInterface $socket): void
{
$this->logger->info("Listening on ".$socket->getAddress()."\n");
$this->server->listen($socket);
}
private function createLogger(): Logger
{
$handlers = [
new StreamHandler(STDOUT)
];
$logger = new Logger("main", $handlers);
return $logger;
$this->logger->info(sprintf(
"Listening on %s",
str_replace("tcp://",($socket instanceof SecureServer?"https://":"http://"),$socket->getAddress())
));
}
/**
@ -89,7 +85,7 @@ class Server
*/
private function createHttpServer(): HttpServer
{
return new HttpServer(
$stack = [
$this->responseMiddleware = new ResponseMiddleware(
config: $this->config,
logger: $this->logger->withName("http"),
@ -97,11 +93,18 @@ class Server
$this->securityMiddleware = new SecurityMiddleware(
config: $this->config
),
$this->webSocketHandler = new WebSocketHandler(
config: $this->config,
webSocketClients: $this->webSocketClients,
topicManager: $this->topicManager
),
];
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,
$this->mercureHandler = new MercureHandler(
config: $this->config,
topicManager: $this->topicManager
@ -111,7 +114,9 @@ class Server
topicManager: $this->topicManager
),
$this->notFoundHandler = new NotFoundHandler()
);
];
return new HttpServer(...$stack);
}