This commit is contained in:
Marcel Pociot 2018-11-24 00:06:28 +01:00
parent a5c7437895
commit f8008ea95e
13 changed files with 233 additions and 2 deletions

View File

@ -4,6 +4,11 @@ use BeyondCode\LaravelWebSockets\ClientProviders\ConfigClientProvider;
return [ return [
/*
* Path for the Websockets debug console
*/
'path' => '/websockets',
/* /*
* TODO: add the laravel style comment here * TODO: add the laravel style comment here
*/ */

View File

@ -0,0 +1,83 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>WebSockets Console</title>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://js.pusher.com/4.3/pusher.min.js"></script>
</head>
<body>
<div class="container">
<div class="panel panel-default">
<div id="status"></div>
<div class="panel-heading">
<span class="panel-title">WebSockets Console</span>
<form id="connect" class="form-inline" role="form">
<div class="form-group">
<label class="sr-only" for="appKey">App Key</label>
<input class="form-control" value="{{ env('PUSHER_APP_KEY') }}" id="appKey" placeholder="Enter App Key">
</div>
<div class="form-group">
<label class="sr-only" for="secret">Secret</label>
<input type="password" class="form-control" id="secret" placeholder="Secret">
</div>
<button type="submit" class="btn btn-primary">Connect</button>
</form>
<form id="disconnect" class="form-inline" role="form">
<button type="submit" class="btn btn-danger">Disconnect</button>
</form>
</div>
<div class="panel-body col-md-8">
<h3>Events <span class="badge" id="counter"></span></h3>
<table id="events" class="table table-striped table-hover">
<thead>
<tr>
<th>Type</th>
<th>Socket</th>
<th>Details</th>
<th>Time</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
<script>
$(function(){
$('#connect').submit(function(event) {
var appKey = $('#appKey').val();
var secret = $('#secret').val();
connect(appKey, secret);
event.preventDefault();
});
$('#disconnect').submit(function(event) {
var appKey = $('#appKey').val("");
var secret = $('#secret').val("");
event.preventDefault();
});
});
function connect(appKey, secret) {
pusher = new Pusher(appKey, {
wsHost: window.location.hostname,
wsPort: 6001,
wsPath: '/console',
authEndpoint: '{{ config('websockets.path') }}/auth',
enabledTransports: ['ws', 'flash']
});
var channel = pusher.subscribe('private-logger-new_connection');
channel.bind('private-logger-connection', function(data) {
alert(JSON.stringify(data));
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,14 @@
<?php
namespace BeyondCode\LaravelWebsockets\Http\Controllers;
use Illuminate\Contracts\Broadcasting\Broadcaster;
use Illuminate\Http\Request;
class AuthenticateConsole
{
public function __invoke(Request $request, Broadcaster $broadcaster)
{
return $broadcaster->validAuthenticationResponse($request, []);
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace BeyondCode\LaravelWebsockets\Http\Controllers;
use Illuminate\Http\Request;
class ShowConsole
{
public function __invoke(Request $request)
{
return view('websockets::console');
}
}

4
src/Http/routes.php Normal file
View File

@ -0,0 +1,4 @@
<?php
Route::get('/', 'ShowConsole');
Route::post('/auth', 'AuthenticateConsole');

View File

@ -30,6 +30,10 @@ class ChannelManager
protected function detectChannelClass($channelId): string protected function detectChannelClass($channelId): string
{ {
if (starts_with($channelId, 'logging-')) {
return LoggingChannel::class;
}
if (starts_with($channelId, 'private-')) { if (starts_with($channelId, 'private-')) {
return PrivateChannel::class; return PrivateChannel::class;
} }

View File

@ -0,0 +1,24 @@
<?php
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels;
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\InvalidConnectionException;
use stdClass;
use Ratchet\ConnectionInterface;
class LoggingChannel extends Channel
{
public function subscribe(ConnectionInterface $connection, stdClass $payload)
{
$this->verifySignature($connection, $payload);
$this->verifyAdministrator($connection);
parent::subscribe($connection, $payload);
}
protected function verifyAdministrator(ConnectionInterface $connection)
{
throw_unless($connection->isAdmin, new InvalidConnectionException());
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions;
class InvalidConnectionException extends PusherException
{
public function __construct()
{
$this->message = 'Invalid Connection';
$this->code = 4009;
}
}

View File

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

View File

@ -0,0 +1,36 @@
<?php
namespace BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket;
use Ratchet\ConnectionInterface;
class ConsoleServer extends PusherServer
{
function onOpen(ConnectionInterface $connection)
{
$this->generateSocketId($connection);
$this->verifyConnection($connection);
$this->establishConnection($connection);
// TODO check connection signature
$connection->isAdmin = true;
}
public function log(string $appId, string $type, string $details)
{
$channelId = "private-logger-{$type}";
$channel = $this->channelManager->find($appId, $channelId);
optional($channel)->broadcast([
'event' => $type,
'channel' => $channelId,
'data' => [
'type' => $type,
'details' => $details
]
]);
}
}

View File

@ -10,15 +10,22 @@ use Ratchet\ConnectionInterface;
use Ratchet\RFC6455\Messaging\MessageInterface; use Ratchet\RFC6455\Messaging\MessageInterface;
use BeyondCode\LaravelWebSockets\WebSocketController; use BeyondCode\LaravelWebSockets\WebSocketController;
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager; use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager;
use BeyondCode\LaravelWebsockets\LaravelEcho\Pusher\Exceptions\PusherException;
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\UnknownAppKeyException;
class PusherServer extends WebSocketController class PusherServer extends WebSocketController
{ {
/** @var \BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager */ /** @var \BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager */
protected $channelManager; protected $channelManager;
public function __construct(ChannelManager $channelManager) /** @var ConsoleServer|null */
protected $consoleServer;
public function __construct(ChannelManager $channelManager, ConsoleServer $consoleServer = null)
{ {
$this->channelManager = $channelManager; $this->channelManager = $channelManager;
$this->consoleServer = $consoleServer;
} }
function onOpen(ConnectionInterface $connection) function onOpen(ConnectionInterface $connection)
@ -28,6 +35,8 @@ class PusherServer extends WebSocketController
$this->verifyConnection($connection); $this->verifyConnection($connection);
$this->establishConnection($connection); $this->establishConnection($connection);
$this->consoleServer->log($connection->appId, 'new_connection', '');
} }
public function onMessage(ConnectionInterface $connection, MessageInterface $message) public function onMessage(ConnectionInterface $connection, MessageInterface $message)

View File

@ -2,8 +2,10 @@
namespace BeyondCode\LaravelWebSockets; namespace BeyondCode\LaravelWebSockets;
use Illuminate\Support\Facades\Route;
use BeyondCode\LaravelWebSockets\ClientProviders\ClientProvider; use BeyondCode\LaravelWebSockets\ClientProviders\ClientProvider;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket\ConsoleServer;
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager; use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager;
class LaravelWebSocketsServiceProvider extends ServiceProvider class LaravelWebSocketsServiceProvider extends ServiceProvider
@ -14,11 +16,30 @@ class LaravelWebSocketsServiceProvider extends ServiceProvider
__DIR__.'/../config/websockets.php' => base_path('config/websockets.php'), __DIR__.'/../config/websockets.php' => base_path('config/websockets.php'),
], 'config'); ], 'config');
$this->registerRoutes();
$this->loadViewsFrom(__DIR__.'/../resources/views/', 'websockets');
$this->commands([ $this->commands([
Console\StartWebSocketServer::class, Console\StartWebSocketServer::class,
]); ]);
} }
protected function registerRoutes()
{
Route::group($this->routeConfiguration(), function () {
$this->loadRoutesFrom(__DIR__.'/Http/routes.php');
});
}
protected function routeConfiguration()
{
return [
'namespace' => 'BeyondCode\LaravelWebSockets\Http\Controllers',
'prefix' => config('websockets.path'),
];
}
public function register() public function register()
{ {
$this->mergeConfigFrom(__DIR__.'/../config/websockets.php', 'websockets'); $this->mergeConfigFrom(__DIR__.'/../config/websockets.php', 'websockets');
@ -34,5 +55,9 @@ class LaravelWebSocketsServiceProvider extends ServiceProvider
$this->app->singleton(ClientProvider::class, function() { $this->app->singleton(ClientProvider::class, function() {
return app(config('websockets.client_provider')); return app(config('websockets.client_provider'));
}); });
$this->app->singleton(ConsoleServer::class, function() {
return new ConsoleServer(new ChannelManager());
});
} }
} }

View File

@ -67,6 +67,8 @@ class Router
{ {
$this->get('/app/{appKey}', LaravelEcho\WebSocket\PusherServer::class); $this->get('/app/{appKey}', LaravelEcho\WebSocket\PusherServer::class);
$this->get('/console/app/{appKey}', LaravelEcho\WebSocket\ConsoleServer::class);
$this->get('/apps/{appId}/channels', LaravelEcho\Http\Controllers\FetchChannels::class); $this->get('/apps/{appId}/channels', LaravelEcho\Http\Controllers\FetchChannels::class);
$this->get('/apps/{appId}/channels/{channelName}', LaravelEcho\Http\Controllers\FetchChannel::class); $this->get('/apps/{appId}/channels/{channelName}', LaravelEcho\Http\Controllers\FetchChannel::class);
$this->get('/apps/{appId}/channels/{channelName}/users', LaravelEcho\Http\Controllers\FetchUsers::class); $this->get('/apps/{appId}/channels/{channelName}/users', LaravelEcho\Http\Controllers\FetchUsers::class);