Merge branch 'master' of github.com:beyondcode/laravel-websockets
This commit is contained in:
commit
2685f48f1e
|
|
@ -1,6 +1,5 @@
|
|||
<?php
|
||||
|
||||
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize;
|
||||
use BeyondCode\LaravelWebSockets\ClientProviders\ConfigClientProvider;
|
||||
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ use Illuminate\Http\JsonResponse;
|
|||
use GuzzleHttp\Psr7\ServerRequest;
|
||||
use Ratchet\Http\HttpServerInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use SebastianBergmann\ObjectEnumerator\Fixtures\ExceptionThrower;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class FetchChannel extends EchoController
|
|||
$channel = $this->channelManager->find($request->appId, $request->channelName);
|
||||
|
||||
if (is_null($channel)) {
|
||||
throw new HttpException(404, 'Unknown channel "'.$request->channelName.'"');
|
||||
throw new HttpException(404, "Unknown channel `{$request->channelName}`.");
|
||||
}
|
||||
|
||||
return $channel->toArray();
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels;
|
|||
use BeyondCode\LaravelWebSockets\Events\ChannelOccupied;
|
||||
use BeyondCode\LaravelWebSockets\Events\ChannelVacated;
|
||||
use BeyondCode\LaravelWebSockets\Events\SubscribedToChannel;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Dashboard;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\InvalidSignatureException;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\InvalidSignature;
|
||||
use Illuminate\Support\Collection;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use stdClass;
|
||||
|
|
@ -40,7 +39,7 @@ class Channel
|
|||
}
|
||||
|
||||
if (str_after($auth, ':') !== hash_hmac('sha256', $signature, $connection->client->appSecret)) {
|
||||
throw new InvalidSignatureException();
|
||||
throw new InvalidSignature();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class ChannelManager
|
|||
return $this->channels[$appId][$channelId] ?? null;
|
||||
}
|
||||
|
||||
protected function detectChannelClass($channelId): string
|
||||
protected function detectChannelClass(string $channelId): string
|
||||
{
|
||||
if (starts_with($channelId, 'private-')) {
|
||||
return PrivateChannel::class;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels;
|
||||
|
||||
use Ratchet\ConnectionInterface;
|
||||
use stdClass;
|
||||
|
||||
class PresenceChannel extends Channel
|
||||
{
|
||||
|
|
@ -16,7 +17,7 @@ class PresenceChannel extends Channel
|
|||
/*
|
||||
* @link https://pusher.com/docs/pusher_protocol#presence-channel-events
|
||||
*/
|
||||
public function subscribe(ConnectionInterface $connection, $payload)
|
||||
public function subscribe(ConnectionInterface $connection, stdClass $payload)
|
||||
{
|
||||
$this->verifySignature($connection, $payload);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions;
|
||||
|
||||
class InvalidConnectionException extends PusherException
|
||||
class InvalidConnection extends PusherException
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions;
|
||||
|
||||
class InvalidSignatureException extends PusherException
|
||||
class InvalidSignature extends PusherException
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions;
|
||||
|
||||
class UnknownAppKeyException extends PusherException
|
||||
class UnknownAppKey extends PusherException
|
||||
{
|
||||
public function __construct(string $appKey)
|
||||
{
|
||||
|
|
@ -4,7 +4,6 @@ namespace BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket;
|
|||
|
||||
use BeyondCode\LaravelWebSockets\Events\ClientMessageSent;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Dashboard;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use stdClass;
|
||||
|
||||
|
|
@ -30,12 +29,14 @@ class Message implements RespondableMessage
|
|||
|
||||
public function respond()
|
||||
{
|
||||
if (starts_with($this->payload->event, 'client-')) {
|
||||
event(new ClientMessageSent($this->connection, $this->payload));
|
||||
|
||||
$channel = $this->channelManager->find($this->connection->client->appId, $this->payload->channel);
|
||||
|
||||
optional($channel)->broadcast($this->payload);
|
||||
if (!starts_with($this->payload->event, 'client-')) {
|
||||
return;
|
||||
}
|
||||
|
||||
event(new ClientMessageSent($this->connection, $this->payload));
|
||||
|
||||
$channel = $this->channelManager->find($this->connection->client->appId, $this->payload->channel);
|
||||
|
||||
optional($channel)->broadcast($this->payload);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket;
|
||||
|
||||
use BeyondCode\LaravelWebSockets\Events\ConnectionEstablished;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Dashboard;
|
||||
use BeyondCode\LaravelWebSockets\QueryParameters;
|
||||
use Exception;
|
||||
use Ratchet\ConnectionInterface;
|
||||
|
|
@ -12,7 +11,7 @@ use BeyondCode\LaravelWebSockets\WebSocketController;
|
|||
use BeyondCode\LaravelWebSockets\ClientProviders\Client;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\PusherException;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\UnknownAppKeyException;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\UnknownAppKey;
|
||||
|
||||
class PusherServer extends WebSocketController
|
||||
{
|
||||
|
|
@ -26,11 +25,10 @@ class PusherServer extends WebSocketController
|
|||
|
||||
function onOpen(ConnectionInterface $connection)
|
||||
{
|
||||
$this->generateSocketId($connection);
|
||||
|
||||
$this->verifyConnection($connection);
|
||||
|
||||
$this->establishConnection($connection);
|
||||
$this
|
||||
->generateSocketId($connection)
|
||||
->verifyConnection($connection)
|
||||
->establishConnection($connection);
|
||||
}
|
||||
|
||||
public function onMessage(ConnectionInterface $connection, MessageInterface $message)
|
||||
|
|
@ -45,7 +43,7 @@ class PusherServer extends WebSocketController
|
|||
$this->channelManager->removeFromAllChannels($connection);
|
||||
}
|
||||
|
||||
function onError(ConnectionInterface $connection, Exception $exception)
|
||||
public function onError(ConnectionInterface $connection, Exception $exception)
|
||||
{
|
||||
if ($exception instanceof PusherException) {
|
||||
$connection->send(json_encode(
|
||||
|
|
@ -54,15 +52,26 @@ class PusherServer extends WebSocketController
|
|||
}
|
||||
}
|
||||
|
||||
protected function generateSocketId(ConnectionInterface $connection)
|
||||
{
|
||||
$socketId = sprintf("%d.%d", getmypid(), random_int(1, 100000000));
|
||||
|
||||
$connection->socketId = $socketId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function verifyConnection(ConnectionInterface $connection)
|
||||
{
|
||||
$appKey = QueryParameters::create($connection->httpRequest)->get('appKey');
|
||||
|
||||
if (! $client = Client::findByAppKey($appKey)) {
|
||||
throw new UnknownAppKeyException($appKey);
|
||||
if (!$client = Client::findByAppKey($appKey)) {
|
||||
throw new UnknownAppKey($appKey);
|
||||
}
|
||||
|
||||
$connection->client = $client;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function establishConnection(ConnectionInterface $connection)
|
||||
|
|
@ -76,12 +85,7 @@ class PusherServer extends WebSocketController
|
|||
]));
|
||||
|
||||
event(new ConnectionEstablished($connection));
|
||||
}
|
||||
|
||||
protected function generateSocketId(ConnectionInterface $connection)
|
||||
{
|
||||
$socketId = sprintf("%d.%d", getmypid(), random_int(1, 100000000));
|
||||
|
||||
$connection->socketId = $socketId;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,33 +3,37 @@
|
|||
namespace BeyondCode\LaravelWebSockets\Tests;
|
||||
|
||||
use BeyondCode\LaravelWebSockets\ClientProviders\Client;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\InvalidSignatureException;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\UnknownAppKeyException;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\InvalidSignature;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\UnknownAppKey;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket\PusherServer;
|
||||
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
|
||||
|
||||
class ConnectionTest extends TestCase
|
||||
{
|
||||
/** @var \BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket\PusherServer */
|
||||
protected $pusherServer;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->pusherServer = app(PusherServer::class);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function unknown_app_keys_can_not_connect()
|
||||
{
|
||||
$this->expectException(UnknownAppKeyException::class);
|
||||
$this->expectException(UnknownAppKey::class);
|
||||
|
||||
/** @var PusherServer $server */
|
||||
$server = app(PusherServer::class);
|
||||
|
||||
$server->onOpen($this->getWebSocketConnection('/?appKey=test'));
|
||||
$this->pusherServer->onOpen($this->getWebSocketConnection('/?appKey=test'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function known_app_keys_can_connect()
|
||||
{
|
||||
/** @var PusherServer $server */
|
||||
$server = app(PusherServer::class);
|
||||
|
||||
$connection = $this->getWebSocketConnection();
|
||||
|
||||
$server->onOpen($connection);
|
||||
$this->pusherServer->onOpen($connection);
|
||||
|
||||
$connection->assertSentEvent('pusher:connection_established');
|
||||
}
|
||||
|
|
@ -37,12 +41,9 @@ class ConnectionTest extends TestCase
|
|||
/** @test */
|
||||
public function successful_connections_have_the_client_attached()
|
||||
{
|
||||
/** @var PusherServer $server */
|
||||
$server = app(PusherServer::class);
|
||||
|
||||
$connection = $this->getWebSocketConnection();
|
||||
|
||||
$server->onOpen($connection);
|
||||
$this->pusherServer->onOpen($connection);
|
||||
|
||||
$this->assertInstanceOf(Client::class, $connection->client);
|
||||
$this->assertSame(1234, $connection->client->appId);
|
||||
|
|
@ -54,16 +55,13 @@ class ConnectionTest extends TestCase
|
|||
/** @test */
|
||||
public function ping_returns_pong()
|
||||
{
|
||||
/** @var PusherServer $server */
|
||||
$server = app(PusherServer::class);
|
||||
|
||||
$connection = $this->getWebSocketConnection();
|
||||
|
||||
$message = new Message('{"event": "pusher:ping"}');
|
||||
|
||||
$server->onOpen($connection);
|
||||
$this->pusherServer->onOpen($connection);
|
||||
|
||||
$server->onMessage($connection, $message);
|
||||
$this->pusherServer->onMessage($connection, $message);
|
||||
|
||||
$connection->assertSentEvent('pusher:pong');
|
||||
}
|
||||
|
|
@ -71,9 +69,6 @@ class ConnectionTest extends TestCase
|
|||
/** @test */
|
||||
public function clients_can_subscribe_to_basic_channels()
|
||||
{
|
||||
/** @var PusherServer $server */
|
||||
$server = app(PusherServer::class);
|
||||
|
||||
$connection = $this->getWebSocketConnection();
|
||||
|
||||
$message = new Message(json_encode([
|
||||
|
|
@ -83,9 +78,9 @@ class ConnectionTest extends TestCase
|
|||
],
|
||||
]));
|
||||
|
||||
$server->onOpen($connection);
|
||||
$this->pusherServer->onOpen($connection);
|
||||
|
||||
$server->onMessage($connection, $message);
|
||||
$this->pusherServer->onMessage($connection, $message);
|
||||
|
||||
$connection->assertSentEvent('pusher_internal:subscription_succeeded', [
|
||||
'channel' => 'basic-channel'
|
||||
|
|
@ -95,10 +90,7 @@ class ConnectionTest extends TestCase
|
|||
/** @test */
|
||||
public function clients_need_valid_auth_signatures_for_private_channels()
|
||||
{
|
||||
$this->expectException(InvalidSignatureException::class);
|
||||
|
||||
/** @var PusherServer $server */
|
||||
$server = app(PusherServer::class);
|
||||
$this->expectException(InvalidSignature::class);
|
||||
|
||||
$connection = $this->getWebSocketConnection();
|
||||
|
||||
|
|
@ -110,20 +102,17 @@ class ConnectionTest extends TestCase
|
|||
],
|
||||
]));
|
||||
|
||||
$server->onOpen($connection);
|
||||
$this->pusherServer->onOpen($connection);
|
||||
|
||||
$server->onMessage($connection, $message);
|
||||
$this->pusherServer->onMessage($connection, $message);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function clients_can_subscribe_to_private_channels()
|
||||
{
|
||||
/** @var PusherServer $server */
|
||||
$server = app(PusherServer::class);
|
||||
|
||||
$connection = $this->getWebSocketConnection();
|
||||
|
||||
$server->onOpen($connection);
|
||||
$this->pusherServer->onOpen($connection);
|
||||
|
||||
$signature = "{$connection->socketId}:private-channel";
|
||||
|
||||
|
|
@ -135,7 +124,7 @@ class ConnectionTest extends TestCase
|
|||
],
|
||||
]));
|
||||
|
||||
$server->onMessage($connection, $message);
|
||||
$this->pusherServer->onMessage($connection, $message);
|
||||
|
||||
$connection->assertSentEvent('pusher_internal:subscription_succeeded', [
|
||||
'channel' => 'private-channel'
|
||||
|
|
@ -145,10 +134,7 @@ class ConnectionTest extends TestCase
|
|||
/** @test */
|
||||
public function clients_need_valid_auth_signatures_for_presence_channels()
|
||||
{
|
||||
$this->expectException(InvalidSignatureException::class);
|
||||
|
||||
/** @var PusherServer $server */
|
||||
$server = app(PusherServer::class);
|
||||
$this->expectException(InvalidSignature::class);
|
||||
|
||||
$connection = $this->getWebSocketConnection();
|
||||
|
||||
|
|
@ -160,20 +146,17 @@ class ConnectionTest extends TestCase
|
|||
],
|
||||
]));
|
||||
|
||||
$server->onOpen($connection);
|
||||
$this->pusherServer->onOpen($connection);
|
||||
|
||||
$server->onMessage($connection, $message);
|
||||
$this->pusherServer->onMessage($connection, $message);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function clients_can_subscribe_to_presence_channels()
|
||||
{
|
||||
/** @var PusherServer $server */
|
||||
$server = app(PusherServer::class);
|
||||
|
||||
$connection = $this->getWebSocketConnection();
|
||||
|
||||
$server->onOpen($connection);
|
||||
$this->pusherServer->onOpen($connection);
|
||||
|
||||
$channelData = [
|
||||
'user_id' => 1,
|
||||
|
|
@ -193,7 +176,7 @@ class ConnectionTest extends TestCase
|
|||
],
|
||||
]));
|
||||
|
||||
$server->onMessage($connection, $message);
|
||||
$this->pusherServer->onMessage($connection, $message);
|
||||
|
||||
$connection->assertSentEvent('pusher_internal:subscription_succeeded', [
|
||||
'channel' => 'presence-channel',
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ class Connection implements ConnectionInterface
|
|||
|
||||
public $sentData = [];
|
||||
|
||||
public $closed = false;
|
||||
|
||||
function send($data)
|
||||
{
|
||||
$this->sentData[] = json_decode($data, true);
|
||||
|
|
@ -20,7 +22,7 @@ class Connection implements ConnectionInterface
|
|||
|
||||
function close()
|
||||
{
|
||||
// TODO: Implement close() method.
|
||||
$this->closed = true;
|
||||
}
|
||||
|
||||
public function assertSentEvent(string $name, array $additionalParameters = [])
|
||||
|
|
@ -35,4 +37,9 @@ class Connection implements ConnectionInterface
|
|||
PHPUnit::assertSame($event[$parameter], $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function assertClosed()
|
||||
{
|
||||
PHPUnit::assertTrue($this->closed);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue