add client provider
This commit is contained in:
parent
193eb5eb4f
commit
d7ea654c3d
|
|
@ -1,5 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use BeyondCode\LaravelWebSockets\ClientProviders\ConfigClientProvider;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -34,27 +36,26 @@ return [
|
||||||
'passphrase' => null
|
'passphrase' => null
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* TODO:: add client config
|
* This package comes with multi tenancy out of the box. Here you can
|
||||||
*
|
* configure the diffente clients that can use the webSockets server.
|
||||||
* Default: one item in the array with env PUSHER_APP_ID, _KEY, _SECRET
|
|
||||||
*
|
|
||||||
* Add notice app id should be numeric
|
|
||||||
*
|
|
||||||
* "clients": [
|
|
||||||
{
|
|
||||||
"appId": "cbf9b001405e51d4",
|
|
||||||
"key": "d886dd1900a5911d00996b41638d7026"
|
|
||||||
"secret":
|
|
||||||
}
|
|
||||||
],
|
|
||||||
`
|
|
||||||
*
|
*
|
||||||
|
* You should make sure that the app id is numeric.
|
||||||
|
*/
|
||||||
'clients' => [
|
'clients' => [
|
||||||
...[]
|
[
|
||||||
|
'app_id' => env('WEBSOCKETS_APP_ID'),
|
||||||
|
'app_key' => env('WEBSOCKETS_APP_KEY'),
|
||||||
|
'app_secret' => env('WEBSOCKETS_APP_SECRET')
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
'client_provider' => ConfigProvider
|
/**
|
||||||
*/
|
* This class is responsible for finding the clients. The default provider
|
||||||
|
* will use the clients defined in this config file.
|
||||||
|
*
|
||||||
|
* You can create a custom provider by implementing the
|
||||||
|
* `ClientProvier` interface.
|
||||||
|
*/
|
||||||
|
'client_provider' => ConfigClientProvider::class,
|
||||||
];
|
];
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BeyondCode\LaravelWebSockets\ClientProviders;
|
||||||
|
|
||||||
|
|
||||||
|
use BeyondCode\LaravelWebSockets\Exceptions\InvalidClient;
|
||||||
|
|
||||||
|
class Client
|
||||||
|
{
|
||||||
|
/** @var int */
|
||||||
|
public $appId;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $appKey;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $appSecret;
|
||||||
|
|
||||||
|
public static function find(string $appKey): ?Client
|
||||||
|
{
|
||||||
|
return app(ClientProvider::class)->findClient($appKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __construct($appId, string $appKey, string $appSecret)
|
||||||
|
{
|
||||||
|
if (!is_numeric($appId)) {
|
||||||
|
throw InvalidClient::appIdIsNotNumeric($appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($appKey === '') {
|
||||||
|
throw InvalidClient::valueIsRequired('appKey', $appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($appSecret === '') {
|
||||||
|
throw InvalidClient::valueIsRequired('appSecret', $appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->appId = $appId;
|
||||||
|
|
||||||
|
$this->appKey = $appKey;
|
||||||
|
|
||||||
|
$this->appSecret = $appSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BeyondCode\LaravelWebSockets\ClientProviders;
|
||||||
|
|
||||||
|
|
||||||
|
interface ClientProvider
|
||||||
|
{
|
||||||
|
public function findClient(string $appId): ?Client;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BeyondCode\LaravelWebSockets\ClientProviders;
|
||||||
|
|
||||||
|
class ConfigClientProvider implements ClientProvider
|
||||||
|
{
|
||||||
|
public function getClients(): array
|
||||||
|
{
|
||||||
|
return config('laravel-websockets.clients');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findClient(string $appKey): ?Client
|
||||||
|
{
|
||||||
|
$allClients = collect(config('websockets.clients'));
|
||||||
|
|
||||||
|
$client = $allClients->firstWhere('app_key', $appKey);
|
||||||
|
|
||||||
|
if (! $client) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Client(
|
||||||
|
$client['app_id'],
|
||||||
|
$client['app_key'],
|
||||||
|
$client['app_secret']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
namespace BeyondCode\LaravelWebSockets\Console;
|
namespace BeyondCode\LaravelWebSockets\Console;
|
||||||
|
|
||||||
use BeyondCode\LaravelWebSockets\Facades\WebSocketRouter;
|
use BeyondCode\LaravelWebSockets\Facades\WebSocketRouter;
|
||||||
|
use BeyondCode\LaravelWebSockets\Server\Logger;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use BeyondCode\LaravelWebSockets\Server\WebSocketServer;
|
use BeyondCode\LaravelWebSockets\Server\WebSocketServer;
|
||||||
|
|
||||||
|
|
@ -16,30 +17,47 @@ class StartWebSocketServer extends Command
|
||||||
|
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
// TODO: add an option to not start the echo server
|
$this
|
||||||
WebSocketRouter::echo();
|
->configureLogger()
|
||||||
|
->registerEchoRoutes()
|
||||||
// TODO: add flag for verbose mode, to send more things to console
|
->startWebSocketServer();
|
||||||
|
|
||||||
$websocketServer = $this->createWebsocketServer();
|
|
||||||
$websocketServer->run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createWebsocketServer(): WebSocketServer
|
protected function configureLogger()
|
||||||
|
{
|
||||||
|
app()->singleton(Logger::class, function() {
|
||||||
|
return (new Logger($this->output))
|
||||||
|
->enable(config('app.debug'))
|
||||||
|
//TODO: use real option
|
||||||
|
->verbose($this->hasOption('vvv'));
|
||||||
|
});
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerEchoRoutes()
|
||||||
|
{
|
||||||
|
WebSocketRouter::echo();
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function startWebSocketServer()
|
||||||
{
|
{
|
||||||
$routes = WebSocketRouter::getRoutes();
|
$routes = WebSocketRouter::getRoutes();
|
||||||
|
|
||||||
$loop = LoopFactory::create();
|
$loop = LoopFactory::create();
|
||||||
|
|
||||||
$loop->futureTick(function () {
|
$loop->futureTick(function () {
|
||||||
$this->info('Started the WebSocket server on port '.$this->option('port'));
|
$this->info("Started the WebSocket server on port {$this->option('port')}");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** 🎩 Start the magic 🎩 */
|
||||||
return (new WebSocketServer($routes))
|
return (new WebSocketServer($routes))
|
||||||
->setHost($this->option('host'))
|
->setHost($this->option('host'))
|
||||||
->setPort($this->option('port'))
|
->setPort($this->option('port'))
|
||||||
->setConsoleOutput($this->output)
|
->setConsoleOutput($this->output)
|
||||||
->enableLogging(config('app.debug'))
|
->setLoop($loop)
|
||||||
->setLoop($loop);
|
->run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BeyondCode\LaravelWebSockets\Exceptions;
|
||||||
|
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class InvalidClient extends Exception
|
||||||
|
{
|
||||||
|
public static function notFound(int $appId)
|
||||||
|
{
|
||||||
|
return new static("Could not find client for app id `{$appId}`.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function appIdIsNotNumeric($appId)
|
||||||
|
{
|
||||||
|
return new static("Invalid app id `{$appId}` found. An app id should be numeric.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function valueIsRequired($name, int $appId)
|
||||||
|
{
|
||||||
|
return new static("{$name} is required but was empty for app id {$appId}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket;
|
namespace BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket;
|
||||||
|
|
||||||
|
use BeyondCode\LaravelWebSockets\ClientProviders\Client;
|
||||||
use BeyondCode\LaravelWebsockets\LaravelEcho\Pusher\Exceptions\PusherException;
|
use BeyondCode\LaravelWebsockets\LaravelEcho\Pusher\Exceptions\PusherException;
|
||||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\UnknownAppKey;
|
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\UnknownAppKey;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
@ -59,12 +60,11 @@ class PusherServer extends WebSocketController
|
||||||
$queryParameters = [];
|
$queryParameters = [];
|
||||||
parse_str($request->getUri()->getQuery(), $queryParameters);
|
parse_str($request->getUri()->getQuery(), $queryParameters);
|
||||||
|
|
||||||
// Todo: Lookup app-id for multi-tenancy support
|
if (! $client = Client::find($queryParameters['appKey'])) {
|
||||||
if ($queryParameters['appKey'] !== config('broadcasting.connections.pusher.key')) {
|
|
||||||
throw new UnknownAppKey($queryParameters['appKey']);
|
throw new UnknownAppKey($queryParameters['appKey']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$connection->appId = config('broadcasting.connections.pusher.app_id');
|
$connection->appId = $client->appId;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function establishConnection(ConnectionInterface $connection)
|
protected function establishConnection(ConnectionInterface $connection)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace BeyondCode\LaravelWebSockets;
|
namespace BeyondCode\LaravelWebSockets;
|
||||||
|
|
||||||
|
use BeyondCode\LaravelWebSockets\ClientProviders\ClientProvider;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager;
|
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager;
|
||||||
|
|
||||||
|
|
@ -10,7 +11,7 @@ class LaravelWebSocketsServiceProvider extends ServiceProvider
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
$this->publishes([
|
$this->publishes([
|
||||||
__DIR__.'/../config/config.php' => base_path('config/websockets.php'),
|
__DIR__.'/../config/websockets.php' => base_path('config/websockets.php'),
|
||||||
], 'config');
|
], 'config');
|
||||||
|
|
||||||
$this->commands([
|
$this->commands([
|
||||||
|
|
@ -20,7 +21,7 @@ class LaravelWebSocketsServiceProvider extends ServiceProvider
|
||||||
|
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
$this->mergeConfigFrom(__DIR__.'/../config/config.php', 'websockets');
|
$this->mergeConfigFrom(__DIR__.'/../config/websockets.php', 'websockets');
|
||||||
|
|
||||||
$this->app->singleton('websockets.router', function() {
|
$this->app->singleton('websockets.router', function() {
|
||||||
return new Router();
|
return new Router();
|
||||||
|
|
@ -29,5 +30,9 @@ class LaravelWebSocketsServiceProvider extends ServiceProvider
|
||||||
$this->app->singleton(ChannelManager::class, function() {
|
$this->app->singleton(ChannelManager::class, function() {
|
||||||
return new ChannelManager();
|
return new ChannelManager();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$this->app->singleton(ClientProvider::class, function() {
|
||||||
|
return app(config('websockets.client_provider'));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ use Ratchet\WebSocket\WsServer;
|
||||||
use Symfony\Component\Routing\Route;
|
use Symfony\Component\Routing\Route;
|
||||||
use Ratchet\Http\HttpServerInterface;
|
use Ratchet\Http\HttpServerInterface;
|
||||||
use Symfony\Component\Routing\RouteCollection;
|
use Symfony\Component\Routing\RouteCollection;
|
||||||
use Ratchet\WebSocket\MessageComponentInterface;
|
|
||||||
use BeyondCode\LaravelWebSockets\Exceptions\InvalidWebSocketController;
|
use BeyondCode\LaravelWebSockets\Exceptions\InvalidWebSocketController;
|
||||||
|
|
||||||
class Router
|
class Router
|
||||||
|
|
@ -82,12 +81,13 @@ class Router
|
||||||
protected function wrapAction($action)
|
protected function wrapAction($action)
|
||||||
{
|
{
|
||||||
if (is_subclass_of($action, WebSocketController::class)) {
|
if (is_subclass_of($action, WebSocketController::class)) {
|
||||||
|
|
||||||
$app = app($action);
|
$app = app($action);
|
||||||
|
|
||||||
$appThatLogs = new Logger($app);
|
if (Logger::isEnabled()) {
|
||||||
|
$app = Logger::decorate($app);
|
||||||
|
}
|
||||||
|
|
||||||
return new WsServer($appThatLogs);
|
return new WsServer($app);
|
||||||
}
|
}
|
||||||
|
|
||||||
return app($action);
|
return app($action);
|
||||||
|
|
|
||||||
|
|
@ -27,22 +27,47 @@ class Logger implements MessageComponentInterface
|
||||||
protected $consoleOutput;
|
protected $consoleOutput;
|
||||||
|
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
protected $enabled;
|
protected $enabled = false;
|
||||||
|
|
||||||
public function __construct(MessageComponentInterface $app)
|
/** @var bool */
|
||||||
|
protected $verbose = false;
|
||||||
|
|
||||||
|
public static function decorate(MessageComponentInterface $app): Logger
|
||||||
|
{
|
||||||
|
$logger = app(Logger::class);
|
||||||
|
|
||||||
|
return $logger->setApp($app);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isEnabled(): bool
|
||||||
|
{
|
||||||
|
return app(Logger::class)->enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __construct(OutputInterface $consoleOutput)
|
||||||
|
{
|
||||||
|
$this->consoleOutput = $consoleOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function enable($enabled = true)
|
||||||
|
{
|
||||||
|
$this->enabled = $enabled;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function verbose($verbose = false)
|
||||||
|
{
|
||||||
|
$this->verbose = $verbose;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setApp(MessageComponentInterface $app)
|
||||||
{
|
{
|
||||||
$this->app = $app;
|
$this->app = $app;
|
||||||
|
|
||||||
/*
|
return $this;
|
||||||
$this->consoleOutput = $consoleOutput;
|
|
||||||
|
|
||||||
$this->enabled = $enabled;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
public function enable()
|
|
||||||
{
|
|
||||||
$this->enabled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onOpen(ConnectionInterface $connection)
|
public function onOpen(ConnectionInterface $connection)
|
||||||
|
|
@ -75,14 +100,13 @@ class Logger implements MessageComponentInterface
|
||||||
{
|
{
|
||||||
$exceptionClass = get_class($exception);
|
$exceptionClass = get_class($exception);
|
||||||
|
|
||||||
$message = "{$connection->appId}: execption `{$exceptionClass}` thrown: `{$exception->getMessage()}`";
|
$appId = $connection->appId ?? 'Unknown app id';
|
||||||
|
|
||||||
/*
|
$message = "{$appId}: exception `{$exceptionClass}` thrown: `{$exception->getMessage()}`";
|
||||||
* TODO: add verbose option
|
|
||||||
if ($this->isVerbose) {
|
if ($this->verbose) {
|
||||||
$message .= $exception->getTraceAsString();
|
$message .= $exception->getTraceAsString();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
$this->error($message);
|
$this->error($message);
|
||||||
|
|
||||||
|
|
@ -106,10 +130,6 @@ class Logger implements MessageComponentInterface
|
||||||
|
|
||||||
protected function line(string $message, string $style)
|
protected function line(string $message, string $style)
|
||||||
{
|
{
|
||||||
echo $message;
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
$styled = $style ? "<$style>$message</$style>" : $message;
|
$styled = $style ? "<$style>$message</$style>" : $message;
|
||||||
|
|
||||||
$this->consoleOutput->writeln($styled);
|
$this->consoleOutput->writeln($styled);
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,6 @@ class WebSocketServer
|
||||||
/** @var Symfony\Component\Console\Output\OutputInterface */
|
/** @var Symfony\Component\Console\Output\OutputInterface */
|
||||||
protected $consoleOutput;
|
protected $consoleOutput;
|
||||||
|
|
||||||
protected $enableLogging = false;
|
|
||||||
|
|
||||||
public function __construct(RouteCollection $routes)
|
public function __construct(RouteCollection $routes)
|
||||||
{
|
{
|
||||||
$this->loop = LoopFactory::create();
|
$this->loop = LoopFactory::create();
|
||||||
|
|
@ -68,13 +66,6 @@ class WebSocketServer
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function enableLogging($enableLogging = true)
|
|
||||||
{
|
|
||||||
$this->enableLogging = $enableLogging;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
$server = $this->createServer();
|
$server = $this->createServer();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue