Implemented subscription logic
This commit is contained in:
@ -102,7 +102,7 @@ ApiHandler::$indexPage = <<<ENDHTML
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
const events = new EventSource("http://127.0.0.1:9000/.well-known/mercure");
|
||||
const events = new EventSource("http://127.0.0.1:9000/.well-known/mercure?topic=https://example.com/books/1");
|
||||
events.onmessage = msg => console.log(msg);
|
||||
</script>
|
||||
</body>
|
||||
|
@ -3,10 +3,11 @@
|
||||
namespace NoccyLabs\Mercureact\Http\Middleware;
|
||||
|
||||
use NoccyLabs\Mercureact\Broker\Message;
|
||||
use NoccyLabs\Mercureact\Broker\SseSubscriber;
|
||||
use NoccyLabs\Mercureact\Broker\TopicManager;
|
||||
use NoccyLabs\Mercureact\Configuration;
|
||||
use NoccyLabs\Mercureact\Http\Exeption\RequestException;
|
||||
use NoccyLabs\Mercureact\Http\Exeption\SecurityException;
|
||||
use NoccyLabs\Mercureact\Http\Exception\RequestException;
|
||||
use NoccyLabs\Mercureact\Http\Exception\SecurityException;
|
||||
use NoccyLabs\SimpleJWT\JWTToken;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
@ -80,9 +81,26 @@ class MercureHandler
|
||||
body: $responseStream
|
||||
);
|
||||
|
||||
$this->eventClients->attach($responseStream, $request);
|
||||
$responseStream->on('close', function () use ($responseStream) {
|
||||
$this->eventClients->detach($responseStream);;
|
||||
$subscriber = new SseSubscriber($responseStream, $request);
|
||||
|
||||
$query = $request->getUri()->getQuery();
|
||||
$query = explode("&", $query);
|
||||
$topics = [];
|
||||
foreach ($query as $param) {
|
||||
if (!str_contains($param, "="))
|
||||
throw new RequestException(
|
||||
message: "Invalid request data",
|
||||
code: RequestException::ERR_INVALID_REQUEST_DATA
|
||||
);
|
||||
[ $name, $value ] = array_map('urldecode', explode("=", $param, 2));
|
||||
if ($name === 'topic') $topics[] = $value;
|
||||
// TODO check claims for access
|
||||
}
|
||||
|
||||
$this->topicManager->subscribe($subscriber, $topics);
|
||||
//$this->eventClients->attach($responseStream, $request);
|
||||
$responseStream->on('close', function () use ($subscriber, $topics) {
|
||||
$this->topicManager->unsubscribe($subscriber, $topics);
|
||||
});
|
||||
|
||||
return $response
|
||||
@ -149,8 +167,9 @@ class MercureHandler
|
||||
return Response::plaintext("urn:uuid:".$message->id."\n");
|
||||
}
|
||||
|
||||
private function checkTopicClaims(string|array $topic, array $claims): bool
|
||||
private function checkTopicClaims(string|array $topic, array $claims, bool $all=false): bool
|
||||
{
|
||||
// TODO match all topics if $all, reject on mismatch
|
||||
foreach ((array)$topic as $match) {
|
||||
foreach ($claims as $claim) {
|
||||
if ($claim === "*") return true;
|
||||
@ -169,6 +188,8 @@ class MercureHandler
|
||||
*/
|
||||
private function publishMercureMessage(Message $message): void
|
||||
{
|
||||
$this->topicManager->publish($message);
|
||||
|
||||
// foreach ($this->webSocketClients as $webSocket) {
|
||||
// $webSocket->write(json_encode([
|
||||
// 'type' => $message->type,
|
||||
|
@ -3,9 +3,10 @@
|
||||
namespace NoccyLabs\Mercureact\Http\Middleware;
|
||||
|
||||
use NoccyLabs\Mercureact\Configuration;
|
||||
use NoccyLabs\Mercureact\Http\Exeption\SecurityException;
|
||||
use NoccyLabs\Mercureact\Http\Exception\SecurityException;
|
||||
use NoccyLabs\SimpleJWT\JWTToken;
|
||||
use NoccyLabs\SimpleJWT\Key\JWTPlaintextKey;
|
||||
use NoccyLabs\SimpleJWT\Validator\JWTValidator;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use React\Promise\Promise;
|
||||
use React\Promise\PromiseInterface;
|
||||
@ -40,7 +41,9 @@ class SecurityMiddleware
|
||||
}
|
||||
|
||||
/**
|
||||
* Check authorization and return a new request with added attributes:
|
||||
*
|
||||
* 'authorization' => JWTToken
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @return ServerRequestInterface
|
||||
@ -53,9 +56,11 @@ class SecurityMiddleware
|
||||
$key = new JWTPlaintextKey($this->config->getJwtSecret());
|
||||
$tok = new JWTToken($key, $jwt);
|
||||
if (!$tok->isValid()) {
|
||||
throw new SecurityException(message:"Invalid token", code:SecurityException::ERR_ACCESS_DENIED);
|
||||
throw new SecurityException(
|
||||
message: "Invalid token",
|
||||
code: SecurityException::ERR_ACCESS_DENIED
|
||||
);
|
||||
}
|
||||
$mercureClaims = $tok->claims->get('mercure');
|
||||
return $request
|
||||
->withAttribute('authorization', $tok);
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user