wip
This commit is contained in:
parent
8faa7bf3f1
commit
b4141c81db
|
|
@ -28,8 +28,10 @@
|
||||||
"illuminate/console": "5.7.*",
|
"illuminate/console": "5.7.*",
|
||||||
"illuminate/http": "5.7.*",
|
"illuminate/http": "5.7.*",
|
||||||
"illuminate/routing": "5.7.*",
|
"illuminate/routing": "5.7.*",
|
||||||
|
"illuminate/broadcasting": "5.7.*",
|
||||||
"illuminate/support": "5.7.*",
|
"illuminate/support": "5.7.*",
|
||||||
"symfony/http-kernel": "~4.0",
|
"symfony/http-kernel": "~4.0",
|
||||||
|
"pusher/pusher-php-server": "~3.0",
|
||||||
"symfony/psr-http-message-bridge": "^1.1"
|
"symfony/psr-http-message-bridge": "^1.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
|
|
||||||
|
|
@ -7,31 +7,53 @@
|
||||||
src="https://code.jquery.com/jquery-3.3.1.min.js"
|
src="https://code.jquery.com/jquery-3.3.1.min.js"
|
||||||
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
|
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
|
||||||
crossorigin="anonymous"></script>
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
|
||||||
<script src="https://js.pusher.com/4.3/pusher.min.js"></script>
|
<script src="https://js.pusher.com/4.3/pusher.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container" id="app">
|
||||||
<div class="panel panel-default">
|
<div class="card col-xs-12">
|
||||||
<div id="status"></div>
|
<div class="card-header">
|
||||||
<div class="panel-heading">
|
|
||||||
<span class="panel-title">WebSockets Console</span>
|
|
||||||
<form id="connect" class="form-inline" role="form">
|
<form id="connect" class="form-inline" role="form">
|
||||||
<div class="form-group">
|
<label class="my-1 mr-2" for="client">Client:</label>
|
||||||
<select class="form-control" name="app" id="app">
|
<select class="form-control form-control-sm mr-2" name="client" id="client" v-model="client">
|
||||||
@foreach ($clients as $client)
|
<option v-for="client in clients" :value="client">@{{ client.name }}</option>
|
||||||
<option value="{{ $client->appKey }}">{{ $client->name }}</option>
|
</select>
|
||||||
@endforeach
|
<label class="my-1 mr-2" for="client">Port:</label>
|
||||||
</select>
|
<input class="form-control form-control-sm mr-2" v-model="port" placeholder="Port">
|
||||||
</div>
|
<button v-if="! connected" type="submit" @click.prevent="connect" class="mr-2 btn btn-sm btn-primary">Connect</button>
|
||||||
<button type="submit" class="btn btn-primary">Connect</button>
|
<button v-if="connected" type="submit" @click.prevent="disconnect" class="btn btn-sm btn-danger">Disconnect</button>
|
||||||
</form>
|
|
||||||
<form id="disconnect" class="form-inline" role="form">
|
|
||||||
<button type="submit" class="btn btn-danger">Disconnect</button>
|
|
||||||
</form>
|
</form>
|
||||||
|
<div id="status"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body col-md-8">
|
<div class="card-body">
|
||||||
<h3>Events <span class="badge" id="counter"></span></h3>
|
<div v-if="connected">
|
||||||
|
<h4>Event Creator</h4>
|
||||||
|
<form>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<input type="text" class="form-control" v-model="form.channel" placeholder="Channel">
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input type="text" class="form-control" v-model="form.event" placeholder="Event">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col">
|
||||||
|
<div class="form-group">
|
||||||
|
<textarea placeholder="Data" v-model="form.data" class="form-control" id="data" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row text-right">
|
||||||
|
<div class="col">
|
||||||
|
<button type="submit" @click.prevent="sendEvent" class="btn btn-sm btn-primary">Send event</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<h4>Events</h4>
|
||||||
<table id="events" class="table table-striped table-hover">
|
<table id="events" class="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -42,38 +64,113 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<tr v-for="log in logs.slice().reverse()">
|
||||||
|
<td><span class="badge" :class="getBadgeClass(log)">@{{ log.type }}</span></td>
|
||||||
|
<td>@{{ log.socketId }}</td>
|
||||||
|
<td>@{{ log.details }}</td>
|
||||||
|
<td>@{{ log.time }}</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
$(function(){
|
new Vue({
|
||||||
$('#connect').submit(function(event) {
|
el: '#app',
|
||||||
connect($('#app').val());
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#disconnect').submit(function(event) {
|
data: {
|
||||||
var appKey = $('#appKey').val("");
|
connected: false,
|
||||||
var secret = $('#secret').val("");
|
pusher: null,
|
||||||
event.preventDefault();
|
port: 6001,
|
||||||
});
|
client: null,
|
||||||
|
clients: {!! json_encode($clients) !!},
|
||||||
|
form: {
|
||||||
|
channel: null,
|
||||||
|
event: null,
|
||||||
|
data: null
|
||||||
|
},
|
||||||
|
logs: [],
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
connect() {
|
||||||
|
this.pusher = new Pusher(this.client.appKey, {
|
||||||
|
wsHost: window.location.hostname,
|
||||||
|
wsPort: this.port,
|
||||||
|
authEndpoint: '{{ config('websockets.dashboard.path') }}/auth',
|
||||||
|
enabledTransports: ['ws', 'flash']
|
||||||
|
});
|
||||||
|
|
||||||
|
this.pusher.connection.bind('state_change', states => {
|
||||||
|
$('div#status').text("Channels current state is " + states.current);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.pusher.connection.bind('connected', () => {
|
||||||
|
this.connected = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.pusher.connection.bind('disconnected', () => {
|
||||||
|
this.connected = false;
|
||||||
|
this.logs = [];
|
||||||
|
});
|
||||||
|
|
||||||
|
this.subscribeToChannel('disconnection');
|
||||||
|
|
||||||
|
this.subscribeToChannel('connection');
|
||||||
|
|
||||||
|
this.subscribeToChannel('vacated');
|
||||||
|
|
||||||
|
this.subscribeToChannel('occupied');
|
||||||
|
|
||||||
|
this.subscribeToChannel('subscribed');
|
||||||
|
|
||||||
|
this.subscribeToChannel('client_message');
|
||||||
|
|
||||||
|
this.subscribeToChannel('api_message');
|
||||||
|
},
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
this.pusher.disconnect();
|
||||||
|
},
|
||||||
|
|
||||||
|
subscribeToChannel(channel) {
|
||||||
|
this.pusher.subscribe('{{ \BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Dashboard::LOG_CHANNEL_PREFIX }}'+channel)
|
||||||
|
.bind('log_message', (data) => {
|
||||||
|
this.logs.push(data);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getBadgeClass(log) {
|
||||||
|
if (log.type === 'occupied' || log.type === 'connection') {
|
||||||
|
return 'badge-primary';
|
||||||
|
}
|
||||||
|
if (log.type === 'vacated') {
|
||||||
|
return 'badge-warning';
|
||||||
|
}
|
||||||
|
if (log.type === 'disconnection') {
|
||||||
|
return 'badge-error';
|
||||||
|
}
|
||||||
|
if (log.type === 'api_message') {
|
||||||
|
return 'badge-info';
|
||||||
|
}
|
||||||
|
return 'badge-secondary';
|
||||||
|
},
|
||||||
|
|
||||||
|
sendEvent() {
|
||||||
|
$.post('{{ config('websockets.dashboard.path') }}/event', {
|
||||||
|
key: this.client.appKey,
|
||||||
|
secret: this.client.appSecret,
|
||||||
|
appId: this.client.appId,
|
||||||
|
channel: this.form.channel,
|
||||||
|
event: this.form.event,
|
||||||
|
data: this.form.data,
|
||||||
|
}).fail(e => {
|
||||||
|
alert('Error sending event.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function connect(appKey) {
|
|
||||||
pusher = new Pusher(appKey, {
|
|
||||||
wsHost: window.location.hostname,
|
|
||||||
wsPort: 6001,
|
|
||||||
authEndpoint: '{{ config('websockets.dashboard.path') }}/auth',
|
|
||||||
enabledTransports: ['ws', 'flash']
|
|
||||||
});
|
|
||||||
|
|
||||||
pusher.subscribe('private-logger-new_connection')
|
|
||||||
.bind('private-logger-connection', function(data) {
|
|
||||||
alert(JSON.stringify(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BeyondCode\LaravelWebsockets\Http\Controllers;
|
||||||
|
|
||||||
|
use Pusher\Pusher;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Broadcasting\Broadcasters\PusherBroadcaster;
|
||||||
|
|
||||||
|
class SendMessage
|
||||||
|
{
|
||||||
|
public function __invoke(Request $request)
|
||||||
|
{
|
||||||
|
$pusher = new Pusher(
|
||||||
|
$request->key, $request->secret,
|
||||||
|
$request->appId, config('broadcasting.connections.pusher.options', [])
|
||||||
|
);
|
||||||
|
|
||||||
|
return (new PusherBroadcaster($pusher))
|
||||||
|
->broadcast([$request->channel], $request->event, json_decode($request->data, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,3 +2,4 @@
|
||||||
|
|
||||||
Route::get('/', 'ShowConsole');
|
Route::get('/', 'ShowConsole');
|
||||||
Route::post('/auth', 'AuthenticateConsole');
|
Route::post('/auth', 'AuthenticateConsole');
|
||||||
|
Route::post('/event', 'SendMessage');
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Http\Controllers;
|
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Http\Controllers;
|
||||||
|
|
||||||
|
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Dashboard;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class TriggerEvent extends EchoController
|
class TriggerEvent extends EchoController
|
||||||
|
|
@ -11,6 +12,8 @@ class TriggerEvent extends EchoController
|
||||||
$this->verifySignature($request);
|
$this->verifySignature($request);
|
||||||
|
|
||||||
foreach ($request->json()->get('channels', []) as $channelId) {
|
foreach ($request->json()->get('channels', []) as $channelId) {
|
||||||
|
Dashboard::apiMessage($request->appId, $channelId, $request->json()->get('name'), $request->json()->get('data'));
|
||||||
|
|
||||||
$channel = $this->channelManager->find($request->appId, $channelId);
|
$channel = $this->channelManager->find($request->appId, $channelId);
|
||||||
|
|
||||||
optional($channel)->broadcastToEveryoneExcept([
|
optional($channel)->broadcastToEveryoneExcept([
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels;
|
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels;
|
||||||
|
|
||||||
|
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Dashboard;
|
||||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\InvalidSignatureException;
|
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\InvalidSignatureException;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Ratchet\ConnectionInterface;
|
use Ratchet\ConnectionInterface;
|
||||||
|
|
@ -56,11 +57,21 @@ class Channel
|
||||||
public function unsubscribe(ConnectionInterface $connection)
|
public function unsubscribe(ConnectionInterface $connection)
|
||||||
{
|
{
|
||||||
unset($this->subscriptions[$connection->socketId]);
|
unset($this->subscriptions[$connection->socketId]);
|
||||||
|
|
||||||
|
if (! $this->hasConnections()) {
|
||||||
|
Dashboard::vacated($connection, $this->channelId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function saveConnection(ConnectionInterface $connection)
|
protected function saveConnection(ConnectionInterface $connection)
|
||||||
{
|
{
|
||||||
|
if (! $this->hasConnections()) {
|
||||||
|
Dashboard::occupied($connection, $this->channelId);
|
||||||
|
}
|
||||||
|
|
||||||
$this->subscriptions[$connection->socketId] = $connection;
|
$this->subscriptions[$connection->socketId] = $connection;
|
||||||
|
|
||||||
|
Dashboard::subscribed($connection, $this->channelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function broadcast($payload)
|
public function broadcast($payload)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher;
|
||||||
|
|
||||||
|
use Ratchet\ConnectionInterface;
|
||||||
|
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
|
class Dashboard
|
||||||
|
{
|
||||||
|
const LOG_CHANNEL_PREFIX = 'private-websockets-dashboard-';
|
||||||
|
|
||||||
|
const TYPE_DISCONNECTION = 'disconnection';
|
||||||
|
|
||||||
|
const TYPE_CONNECTION = 'connection';
|
||||||
|
|
||||||
|
const TYPE_VACATED = 'vacated';
|
||||||
|
|
||||||
|
const TYPE_OCCUPIED = 'occupied';
|
||||||
|
|
||||||
|
const TYPE_SUBSCRIBED = 'subscribed';
|
||||||
|
|
||||||
|
const TYPE_CLIENT_MESSAGE = 'client_message';
|
||||||
|
|
||||||
|
const TYPE_API_MESSAGE = 'api_message';
|
||||||
|
|
||||||
|
public static function connection(ConnectionInterface $connection)
|
||||||
|
{
|
||||||
|
/** @var \GuzzleHttp\Psr7\Request $request */
|
||||||
|
$request = $connection->httpRequest;
|
||||||
|
|
||||||
|
self::log($connection->client->appId, self::TYPE_CONNECTION, [
|
||||||
|
'details' => "Origin: {$request->getUri()->getScheme()}://{$request->getUri()->getHost()}",
|
||||||
|
'socketId' => $connection->socketId,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function disconnection(ConnectionInterface $connection)
|
||||||
|
{
|
||||||
|
self::log($connection->client->appId, self::TYPE_DISCONNECTION, [
|
||||||
|
'socketId' => $connection->socketId
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function vacated(ConnectionInterface $connection, string $channelId)
|
||||||
|
{
|
||||||
|
self::log($connection->client->appId, self::TYPE_VACATED, [
|
||||||
|
'details' => "Channel: {$channelId}"
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function occupied(ConnectionInterface $connection, string $channelId)
|
||||||
|
{
|
||||||
|
self::log($connection->client->appId, self::TYPE_OCCUPIED, [
|
||||||
|
'details' => "Channel: {$channelId}"
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function subscribed(ConnectionInterface $connection, string $channelId)
|
||||||
|
{
|
||||||
|
self::log($connection->client->appId, self::TYPE_SUBSCRIBED, [
|
||||||
|
'socketId' => $connection->socketId,
|
||||||
|
'details' => "Channel: {$channelId}"
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function clientMessage(ConnectionInterface $connection, stdClass $payload)
|
||||||
|
{
|
||||||
|
self::log($connection->client->appId, self::TYPE_CLIENT_MESSAGE, [
|
||||||
|
'details' => "Channel: {$payload->channel}, Event: {$payload->event}",
|
||||||
|
'socketId' => $connection->socketId,
|
||||||
|
'data' => json_encode($payload)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function apiMessage($appId, string $channel, string $event, string $payload)
|
||||||
|
{
|
||||||
|
self::log($appId, self::TYPE_API_MESSAGE, [
|
||||||
|
'details' => "Channel: {$channel}, Event: {$event}",
|
||||||
|
'data' => $payload
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function log($appId, string $type, array $attributes = [])
|
||||||
|
{
|
||||||
|
$channelId = self::LOG_CHANNEL_PREFIX . $type;
|
||||||
|
|
||||||
|
$channel = app(ChannelManager::class)->find($appId, $channelId);
|
||||||
|
|
||||||
|
optional($channel)->broadcast([
|
||||||
|
'event' => 'log_message',
|
||||||
|
'channel' => $channelId,
|
||||||
|
'data' => [
|
||||||
|
'type' => $type,
|
||||||
|
'time' => strftime("%H:%M:%S")
|
||||||
|
] + $attributes
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket;
|
namespace BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket;
|
||||||
|
|
||||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager;
|
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager;
|
||||||
|
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Dashboard;
|
||||||
use Ratchet\ConnectionInterface;
|
use Ratchet\ConnectionInterface;
|
||||||
use stdClass;
|
use stdClass;
|
||||||
|
|
||||||
|
|
@ -29,6 +30,8 @@ class Message implements RespondableMessage
|
||||||
public function respond()
|
public function respond()
|
||||||
{
|
{
|
||||||
if (starts_with($this->payload->event, 'client-')) {
|
if (starts_with($this->payload->event, 'client-')) {
|
||||||
|
Dashboard::clientMessage($this->connection, $this->payload);
|
||||||
|
|
||||||
$channel = $this->channelManager->find($this->connection->client->appId, $this->payload->channel);
|
$channel = $this->channelManager->find($this->connection->client->appId, $this->payload->channel);
|
||||||
|
|
||||||
optional($channel)->broadcast($this->payload);
|
optional($channel)->broadcast($this->payload);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket;
|
namespace BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket;
|
||||||
|
|
||||||
|
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Dashboard;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Ratchet\ConnectionInterface;
|
use Ratchet\ConnectionInterface;
|
||||||
use Ratchet\RFC6455\Messaging\MessageInterface;
|
use Ratchet\RFC6455\Messaging\MessageInterface;
|
||||||
|
|
@ -68,6 +69,8 @@ class PusherServer extends WebSocketController
|
||||||
|
|
||||||
protected function establishConnection(ConnectionInterface $connection)
|
protected function establishConnection(ConnectionInterface $connection)
|
||||||
{
|
{
|
||||||
|
Dashboard::connection($connection);
|
||||||
|
|
||||||
$connection->send(json_encode([
|
$connection->send(json_encode([
|
||||||
'event' => 'pusher:connection_established',
|
'event' => 'pusher:connection_established',
|
||||||
'data' => json_encode([
|
'data' => json_encode([
|
||||||
|
|
@ -83,20 +86,4 @@ class PusherServer extends WebSocketController
|
||||||
|
|
||||||
$connection->socketId = $socketId;
|
$connection->socketId = $socketId;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue