Configuration fixes, makefile tweaks
* The PHAR now gets tagged with version and buildtime * WebSocket support can now be disabled
This commit is contained in:
parent
da450b510a
commit
b3476881e1
1
Makefile
1
Makefile
@ -13,6 +13,7 @@ phar: ## Build .phar using pharlite
|
|||||||
git clone $(REPODIR) $(BUILDDIR) && \
|
git clone $(REPODIR) $(BUILDDIR) && \
|
||||||
cd $(BUILDDIR) && \
|
cd $(BUILDDIR) && \
|
||||||
composer install --no-dev && \
|
composer install --no-dev && \
|
||||||
|
echo "<?php return [ 'version' => '$(shell git describe --tags)', 'buildtime' => '$(shell date)' ];" > src/meta && \
|
||||||
pharlite
|
pharlite
|
||||||
mv $(BUILDDIR)/*.phar $(REPODIR) && \
|
mv $(BUILDDIR)/*.phar $(REPODIR) && \
|
||||||
rm -rf $(BUILDDIR)
|
rm -rf $(BUILDDIR)
|
||||||
|
@ -3,15 +3,25 @@
|
|||||||
|
|
||||||
use NoccyLabs\Mercureact\Configuration;
|
use NoccyLabs\Mercureact\Configuration;
|
||||||
use NoccyLabs\Mercureact\Daemon;
|
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");
|
$opts = getopt("c:C:h");
|
||||||
|
|
||||||
if (isset($opts['h'])) {
|
if (isset($opts['h'])) {
|
||||||
|
$info = "v".MERCUREACT_VERSION.(MERCUREACT_BUILDTIME?("\nBuilt on ".MERCUREACT_BUILDTIME):"");
|
||||||
fwrite(STDERR, <<<HELP
|
fwrite(STDERR, <<<HELP
|
||||||
Mercureact Realtime SSE Daemon
|
Mercureact Realtime SSE Daemon {$info}
|
||||||
(c) 2024, NoccyLabs - Distributed under GNU GPL v3 or later.
|
(c) 2024, NoccyLabs - Distributed under GNU GPL v3 or later.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
@ -32,8 +42,9 @@ if (isset($opts['C'])) {
|
|||||||
}
|
}
|
||||||
file_put_contents($file, <<<DEFAULTS
|
file_put_contents($file, <<<DEFAULTS
|
||||||
server:
|
server:
|
||||||
public_url: https://example.com
|
|
||||||
address: 0.0.0.0:9000
|
address: 0.0.0.0:9000
|
||||||
|
public_url: https://example.com
|
||||||
|
websockets: false
|
||||||
cors:
|
cors:
|
||||||
allow_origin: '*'
|
allow_origin: '*'
|
||||||
csp: "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'"
|
csp: "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'"
|
||||||
@ -41,9 +52,6 @@ if (isset($opts['C'])) {
|
|||||||
cert: foo.pem
|
cert: foo.pem
|
||||||
key: foo.key
|
key: foo.key
|
||||||
|
|
||||||
websocket:
|
|
||||||
enable: true
|
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
overwrite_id: false
|
overwrite_id: false
|
||||||
reject_duplicates: true
|
reject_duplicates: true
|
||||||
@ -71,4 +79,4 @@ if (isset($opts['c'])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$daemon = new Daemon($config);
|
$daemon = new Daemon($config);
|
||||||
$daemon->start();
|
$daemon->start();
|
||||||
|
@ -2,3 +2,6 @@
|
|||||||
|
|
||||||
This is alpha quality software. Expect, and please report, any bugs encountered.
|
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.
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
# Please make a copy of me before editing
|
# Please make a copy of me before editing
|
||||||
|
|
||||||
server:
|
server:
|
||||||
|
# Listen address
|
||||||
address: 0.0.0.0:9000
|
address: 0.0.0.0:9000
|
||||||
|
# Enable websocket support (experimental)
|
||||||
|
websockets: false
|
||||||
|
|
||||||
# Setup CORS headers
|
# Setup CORS headers
|
||||||
cors:
|
cors:
|
||||||
@ -16,10 +19,6 @@ server:
|
|||||||
cert: foo.pem
|
cert: foo.pem
|
||||||
key: foo.key
|
key: foo.key
|
||||||
|
|
||||||
# Enable websockets
|
|
||||||
websocket:
|
|
||||||
enable: true
|
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
# Assign a UUID to published messages even if one is already set in the message
|
# Assign a UUID to published messages even if one is already set in the message
|
||||||
overwrite_id: false
|
overwrite_id: false
|
||||||
|
@ -97,5 +97,16 @@ class Configuration
|
|||||||
return $this;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
namespace NoccyLabs\Mercureact;
|
namespace NoccyLabs\Mercureact;
|
||||||
|
|
||||||
|
use Monolog\Handler\StreamHandler;
|
||||||
|
use Monolog\Logger;
|
||||||
use NoccyLabs\Mercureact\Http\Server;
|
use NoccyLabs\Mercureact\Http\Server;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
use React\EventLoop\Loop;
|
use React\EventLoop\Loop;
|
||||||
use React\EventLoop\LoopInterface;
|
use React\EventLoop\LoopInterface;
|
||||||
use React\Socket\SocketServer;
|
use React\Socket\SocketServer;
|
||||||
@ -15,19 +18,33 @@ class Daemon
|
|||||||
|
|
||||||
private Server $server;
|
private Server $server;
|
||||||
|
|
||||||
|
private LoggerInterface $logger;
|
||||||
|
|
||||||
public function __construct(Configuration $config, ?LoopInterface $loop=null)
|
public function __construct(Configuration $config, ?LoopInterface $loop=null)
|
||||||
{
|
{
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
$this->loop = $loop??Loop::get();
|
$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
|
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();
|
$listenAddress = $this->config->getListenAddress();
|
||||||
if (!$listenAddress) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
$socket = new SocketServer("tcp://".$listenAddress);
|
$socket = new SocketServer("tcp://".$listenAddress);
|
||||||
|
@ -13,9 +13,11 @@ use NoccyLabs\Mercureact\Http\Middleware\ResponseMiddleware;
|
|||||||
use NoccyLabs\Mercureact\Http\Middleware\SecurityMiddleware;
|
use NoccyLabs\Mercureact\Http\Middleware\SecurityMiddleware;
|
||||||
use NoccyLabs\Mercureact\Http\Middleware\WebSocketHandler;
|
use NoccyLabs\Mercureact\Http\Middleware\WebSocketHandler;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Psr\Log\NullLogger;
|
||||||
use React\EventLoop\Loop;
|
use React\EventLoop\Loop;
|
||||||
use React\EventLoop\LoopInterface;
|
use React\EventLoop\LoopInterface;
|
||||||
use React\Http\HttpServer;
|
use React\Http\HttpServer;
|
||||||
|
use React\Socket\SecureServer;
|
||||||
use React\Socket\ServerInterface;
|
use React\Socket\ServerInterface;
|
||||||
use SplObjectStorage;
|
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->loop = $loop??Loop::get();
|
||||||
|
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
|
|
||||||
$this->logger = $this->createLogger();
|
$this->logger = $logger ?? new NullLogger();
|
||||||
|
|
||||||
$this->topicManager = new TopicManager();
|
$this->topicManager = new TopicManager();
|
||||||
$this->loop->addPeriodicTimer(30, function () {
|
$this->loop->addPeriodicTimer(30, function () {
|
||||||
@ -70,17 +72,11 @@ class Server
|
|||||||
*/
|
*/
|
||||||
public function listen(ServerInterface $socket): void
|
public function listen(ServerInterface $socket): void
|
||||||
{
|
{
|
||||||
$this->logger->info("Listening on ".$socket->getAddress()."\n");
|
|
||||||
$this->server->listen($socket);
|
$this->server->listen($socket);
|
||||||
}
|
$this->logger->info(sprintf(
|
||||||
|
"Listening on %s",
|
||||||
private function createLogger(): Logger
|
str_replace("tcp://",($socket instanceof SecureServer?"https://":"http://"),$socket->getAddress())
|
||||||
{
|
));
|
||||||
$handlers = [
|
|
||||||
new StreamHandler(STDOUT)
|
|
||||||
];
|
|
||||||
$logger = new Logger("main", $handlers);
|
|
||||||
return $logger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +85,7 @@ class Server
|
|||||||
*/
|
*/
|
||||||
private function createHttpServer(): HttpServer
|
private function createHttpServer(): HttpServer
|
||||||
{
|
{
|
||||||
return new HttpServer(
|
$stack = [
|
||||||
$this->responseMiddleware = new ResponseMiddleware(
|
$this->responseMiddleware = new ResponseMiddleware(
|
||||||
config: $this->config,
|
config: $this->config,
|
||||||
logger: $this->logger->withName("http"),
|
logger: $this->logger->withName("http"),
|
||||||
@ -97,11 +93,18 @@ class Server
|
|||||||
$this->securityMiddleware = new SecurityMiddleware(
|
$this->securityMiddleware = new SecurityMiddleware(
|
||||||
config: $this->config
|
config: $this->config
|
||||||
),
|
),
|
||||||
$this->webSocketHandler = new WebSocketHandler(
|
];
|
||||||
config: $this->config,
|
if ($this->config->getEnableWebSockets()) {
|
||||||
webSocketClients: $this->webSocketClients,
|
$stack = [ ...$stack,
|
||||||
topicManager: $this->topicManager
|
$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(
|
$this->mercureHandler = new MercureHandler(
|
||||||
config: $this->config,
|
config: $this->config,
|
||||||
topicManager: $this->topicManager
|
topicManager: $this->topicManager
|
||||||
@ -111,7 +114,9 @@ class Server
|
|||||||
topicManager: $this->topicManager
|
topicManager: $this->topicManager
|
||||||
),
|
),
|
||||||
$this->notFoundHandler = new NotFoundHandler()
|
$this->notFoundHandler = new NotFoundHandler()
|
||||||
);
|
];
|
||||||
|
|
||||||
|
return new HttpServer(...$stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user