Merge branch 'master' of github.com:beyondcode/laravel-websockets

This commit is contained in:
Marcel Pociot 2018-11-27 09:17:45 +01:00
commit 2685f48f1e
13 changed files with 75 additions and 82 deletions

View File

@ -1,6 +1,5 @@
<?php
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize;
use BeyondCode\LaravelWebSockets\ClientProviders\ConfigClientProvider;
return [

View File

@ -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;

View File

@ -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();

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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);

View File

@ -2,7 +2,7 @@
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions;
class InvalidConnectionException extends PusherException
class InvalidConnection extends PusherException
{
public function __construct()
{

View File

@ -2,7 +2,7 @@
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions;
class InvalidSignatureException extends PusherException
class InvalidSignature extends PusherException
{
public function __construct()
{

View File

@ -2,7 +2,7 @@
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions;
class UnknownAppKeyException extends PusherException
class UnknownAppKey extends PusherException
{
public function __construct(string $appKey)
{

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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',

View File

@ -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);
}
}