Request limiting, config improvements

* Added middleware to limit concurrent  request and request body size
* The default configuration now has the defaults
This commit is contained in:
Chris 2024-03-13 01:54:28 +01:00
parent b730b82ef7
commit dc98f70a06
4 changed files with 33 additions and 11 deletions

View File

@ -50,15 +50,12 @@ if (isset($opts['C'])) {
file_put_contents($file, <<<DEFAULTS
server:
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'"
encryption:
local_cert: ~
local_pk: ~
passphrase: ~
publish:
overwrite_ids: false
@ -78,12 +75,7 @@ if (isset($opts['C'])) {
if (isset($opts['c'])) {
$config = Configuration::fromFile($opts['c']);
} else {
$config = Configuration::createDefault()
->setListenAddress('127.0.0.1:8888')
->setAllowOriginHeader("*")
->setContentSecurityPolicyHeader("default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'")
->setAllowAnonymousSubscribe(true)
->setJwtSecret("!ChangeThisMercureHubJWTSecretKey!");
$config = Configuration::createDefault();
}
$verbose = isset($opts['v']);

View File

@ -19,6 +19,13 @@ server:
local_cert: ~
local_pk: ~
passphrase: ~
# Limits
# max_concurent (int) - how many requests that can be handled at once
# max_request_body (int) - max request body size
limits:
max_concurrent: 20
max_request_body: 102400
publish:
# Assign a UUID to published messages even if one is already set in the message

View File

@ -15,7 +15,18 @@ class Configuration
public static function createDefault(): Configuration
{
return new Configuration();
return new Configuration([
"publish.overwrite_ids" => false,
"publish.reject_duplicates" => false,
"server.address" => "127.0.0.1:9000",
"server.enable_api" => true,
"server.limits.max_concurrent" => 100,
"server.limits.max_request_body" => 102400,
"server.cors.allow_origin" => "*",
"server.cors.csp" => "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'",
"subscribe.allow_anonymous" => true,
"security.jwt_secret" => "!ChangeThisMercureHubJWTSecretKey!",
]);
}
public static function fromFile(string $file): Configuration

View File

@ -17,6 +17,8 @@ use Psr\Log\NullLogger;
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;
use React\Socket\ServerInterface;
use SplObjectStorage;
@ -90,7 +92,15 @@ class Server
*/
private function createHttpServer(): HttpServer
{
$stack = [
$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 = [ ...$stack,
$this->responseMiddleware = new ResponseMiddleware(
config: $this->config,
logger: $this->logger->withName("http"),
@ -99,6 +109,7 @@ class Server
config: $this->config
),
];
if ($this->config->getEnableWebSockets()) {
$stack = [ ...$stack,
$this->webSocketHandler = new WebSocketHandler(
@ -109,6 +120,7 @@ class Server
];
$this->logger->warning("The WebSocket support is incomplete and insecure, but enabling it as requested.");
}
$stack = [ ...$stack,
$this->mercureHandler = new MercureHandler(
config: $this->config,