From c312511d97b0f41fb12e60e58947363325c495c6 Mon Sep 17 00:00:00 2001 From: larswolff Date: Wed, 27 Nov 2024 15:48:53 +0100 Subject: [PATCH] [1.x] Allow publishing to others only when using Redis (#275) * Fix for issue #246 Pass SocketID through redis, and filter it on the receiving end. This ensures that ->toOthers() works with scaling = true * update tests * formatting * wip * Update PusherPubSubIncomingMessageHandler.php --------- Co-authored-by: Joe Dixon Co-authored-by: Taylor Otwell --- src/Protocols/Pusher/EventDispatcher.php | 1 + .../PusherPubSubIncomingMessageHandler.php | 7 +++++- .../Pusher/Reverb/EventsControllerTest.php | 23 +++++++++++++++++++ tests/Unit/EventTest.php | 2 +- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/Protocols/Pusher/EventDispatcher.php b/src/Protocols/Pusher/EventDispatcher.php index b94b5f39..fe5830ab 100644 --- a/src/Protocols/Pusher/EventDispatcher.php +++ b/src/Protocols/Pusher/EventDispatcher.php @@ -28,6 +28,7 @@ public static function dispatch(Application $app, array $payload, ?Connection $c 'type' => 'message', 'application' => serialize($app), 'payload' => $payload, + 'socket_id' => $connection?->id(), ]); } diff --git a/src/Protocols/Pusher/PusherPubSubIncomingMessageHandler.php b/src/Protocols/Pusher/PusherPubSubIncomingMessageHandler.php index 55db23e3..aba121e0 100644 --- a/src/Protocols/Pusher/PusherPubSubIncomingMessageHandler.php +++ b/src/Protocols/Pusher/PusherPubSubIncomingMessageHandler.php @@ -16,10 +16,15 @@ public function handle(string $payload): void $application = unserialize($event['application']); + $except = isset($event['socket_id']) ? + app(ChannelManager::class)->for($application)->connections()[$event['socket_id']] ?? null + : null; + match ($event['type'] ?? null) { 'message' => EventDispatcher::dispatchSynchronously( $application, - $event['payload'] + $event['payload'], + $except?->connection() ), 'metrics' => app(MetricsHandler::class)->publish( $application, diff --git a/tests/Feature/Protocols/Pusher/Reverb/EventsControllerTest.php b/tests/Feature/Protocols/Pusher/Reverb/EventsControllerTest.php index a747e286..91b0fde9 100644 --- a/tests/Feature/Protocols/Pusher/Reverb/EventsControllerTest.php +++ b/tests/Feature/Protocols/Pusher/Reverb/EventsControllerTest.php @@ -78,6 +78,29 @@ expect($response->getBody()->getContents())->toBe('{}'); }); +it('can ignore a subscriber when publishing events over redis', function () { + $this->usingRedis(); + + $connection = connect(); + subscribe('test-channel-two', connection: $connection); + $response = await($this->signedPostRequest('events', [ + 'name' => 'NewEvent', + 'channels' => ['test-channel-one', 'test-channel-two'], + 'data' => json_encode(['some' => 'data']), + ])); + + $response = await($this->signedPostRequest('events', [ + 'name' => 'NewEvent', + 'channels' => ['test-channel-one', 'test-channel-two'], + 'data' => json_encode(['some' => 'data']), + 'socket_id' => $connection->socketId(), + ])); + + $connection->assertReceived('{"event":"NewEvent","data":"{\"some\":\"data\"}","channel":"test-channel-two"}', 1); + expect($response->getStatusCode())->toBe(200); + expect($response->getBody()->getContents())->toBe('{}'); +}); + it('does not fail when ignoring an invalid subscriber', function () { $connection = connect(); subscribe('test-channel-two', connection: $connection); diff --git a/tests/Unit/EventTest.php b/tests/Unit/EventTest.php index 7faa109c..d078c721 100644 --- a/tests/Unit/EventTest.php +++ b/tests/Unit/EventTest.php @@ -11,7 +11,7 @@ app(ServerProviderManager::class)->withPublishing(); $pubSub = Mockery::mock(PubSubProvider::class); $pubSub->shouldReceive('publish')->once() - ->with(['type' => 'message', 'application' => serialize($app), 'payload' => ['channel' => 'test-channel']]); + ->with(['type' => 'message', 'application' => serialize($app), 'payload' => ['channel' => 'test-channel'], 'socket_id' => null]); $this->app->instance(PubSubProvider::class, $pubSub);