wip
This commit is contained in:
parent
8faa7bf3f1
commit
b4141c81db
|
|
@ -28,8 +28,10 @@
|
|||
"illuminate/console": "5.7.*",
|
||||
"illuminate/http": "5.7.*",
|
||||
"illuminate/routing": "5.7.*",
|
||||
"illuminate/broadcasting": "5.7.*",
|
||||
"illuminate/support": "5.7.*",
|
||||
"symfony/http-kernel": "~4.0",
|
||||
"pusher/pusher-php-server": "~3.0",
|
||||
"symfony/psr-http-message-bridge": "^1.1"
|
||||
},
|
||||
"require-dev": {
|
||||
|
|
|
|||
|
|
@ -7,31 +7,53 @@
|
|||
src="https://code.jquery.com/jquery-3.3.1.min.js"
|
||||
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
|
||||
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>
|
||||
</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>
|
||||
<div class="container" id="app">
|
||||
<div class="card col-xs-12">
|
||||
<div class="card-header">
|
||||
<form id="connect" class="form-inline" role="form">
|
||||
<div class="form-group">
|
||||
<select class="form-control" name="app" id="app">
|
||||
@foreach ($clients as $client)
|
||||
<option value="{{ $client->appKey }}">{{ $client->name }}</option>
|
||||
@endforeach
|
||||
<label class="my-1 mr-2" for="client">Client:</label>
|
||||
<select class="form-control form-control-sm mr-2" name="client" id="client" v-model="client">
|
||||
<option v-for="client in clients" :value="client">@{{ client.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Connect</button>
|
||||
<label class="my-1 mr-2" for="client">Port:</label>
|
||||
<input class="form-control form-control-sm mr-2" v-model="port" placeholder="Port">
|
||||
<button v-if="! connected" type="submit" @click.prevent="connect" class="mr-2 btn btn-sm 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>
|
||||
<div id="status"></div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<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>
|
||||
<div class="panel-body col-md-8">
|
||||
<h3>Events <span class="badge" id="counter"></span></h3>
|
||||
<h4>Events</h4>
|
||||
<table id="events" class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -42,38 +64,113 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<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>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function(){
|
||||
$('#connect').submit(function(event) {
|
||||
connect($('#app').val());
|
||||
event.preventDefault();
|
||||
});
|
||||
new Vue({
|
||||
el: '#app',
|
||||
|
||||
$('#disconnect').submit(function(event) {
|
||||
var appKey = $('#appKey').val("");
|
||||
var secret = $('#secret').val("");
|
||||
event.preventDefault();
|
||||
});
|
||||
});
|
||||
data: {
|
||||
connected: false,
|
||||
pusher: null,
|
||||
port: 6001,
|
||||
client: null,
|
||||
clients: {!! json_encode($clients) !!},
|
||||
form: {
|
||||
channel: null,
|
||||
event: null,
|
||||
data: null
|
||||
},
|
||||
logs: [],
|
||||
},
|
||||
|
||||
function connect(appKey) {
|
||||
pusher = new Pusher(appKey, {
|
||||
methods: {
|
||||
connect() {
|
||||
this.pusher = new Pusher(this.client.appKey, {
|
||||
wsHost: window.location.hostname,
|
||||
wsPort: 6001,
|
||||
wsPort: this.port,
|
||||
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));
|
||||
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.');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</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::post('/auth', 'AuthenticateConsole');
|
||||
Route::post('/event', 'SendMessage');
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Http\Controllers;
|
||||
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Dashboard;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TriggerEvent extends EchoController
|
||||
|
|
@ -11,6 +12,8 @@ class TriggerEvent extends EchoController
|
|||
$this->verifySignature($request);
|
||||
|
||||
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);
|
||||
|
||||
optional($channel)->broadcastToEveryoneExcept([
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels;
|
||||
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Dashboard;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\InvalidSignatureException;
|
||||
use Illuminate\Support\Collection;
|
||||
use Ratchet\ConnectionInterface;
|
||||
|
|
@ -56,11 +57,21 @@ class Channel
|
|||
public function unsubscribe(ConnectionInterface $connection)
|
||||
{
|
||||
unset($this->subscriptions[$connection->socketId]);
|
||||
|
||||
if (! $this->hasConnections()) {
|
||||
Dashboard::vacated($connection, $this->channelId);
|
||||
}
|
||||
}
|
||||
|
||||
protected function saveConnection(ConnectionInterface $connection)
|
||||
{
|
||||
if (! $this->hasConnections()) {
|
||||
Dashboard::occupied($connection, $this->channelId);
|
||||
}
|
||||
|
||||
$this->subscriptions[$connection->socketId] = $connection;
|
||||
|
||||
Dashboard::subscribed($connection, $this->channelId);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager;
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Dashboard;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use stdClass;
|
||||
|
||||
|
|
@ -29,6 +30,8 @@ class Message implements RespondableMessage
|
|||
public function respond()
|
||||
{
|
||||
if (starts_with($this->payload->event, 'client-')) {
|
||||
Dashboard::clientMessage($this->connection, $this->payload);
|
||||
|
||||
$channel = $this->channelManager->find($this->connection->client->appId, $this->payload->channel);
|
||||
|
||||
optional($channel)->broadcast($this->payload);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace BeyondCode\LaravelWebSockets\LaravelEcho\WebSocket;
|
||||
|
||||
use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Dashboard;
|
||||
use Exception;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Ratchet\RFC6455\Messaging\MessageInterface;
|
||||
|
|
@ -68,6 +69,8 @@ class PusherServer extends WebSocketController
|
|||
|
||||
protected function establishConnection(ConnectionInterface $connection)
|
||||
{
|
||||
Dashboard::connection($connection);
|
||||
|
||||
$connection->send(json_encode([
|
||||
'event' => 'pusher:connection_established',
|
||||
'data' => json_encode([
|
||||
|
|
@ -83,20 +86,4 @@ class PusherServer extends WebSocketController
|
|||
|
||||
$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