Merge branch 'master' into redis-replication

This commit is contained in:
rennokki 2020-08-13 09:59:01 +03:00 committed by GitHub
commit aa1c11e149
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
73 changed files with 1224 additions and 186 deletions

48
.github/workflows/run-tests.yml vendored Normal file
View File

@ -0,0 +1,48 @@
name: run-tests
on: [push, pull_request]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
php: [7.4, 7.3, 7.2]
laravel: [5.8.*, 6.*, 7.*]
dependency-version: [prefer-lowest, prefer-stable]
include:
- laravel: 7.*
testbench: 5.*
- laravel: 6.*
testbench: 4.*
- laravel: 5.8.*
testbench: 3.8.*
name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} - ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v1
- name: Cache dependencies
uses: actions/cache@v1
with:
path: ~/.composer/cache/files
key: dependencies-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick
coverage: none
- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest
- name: Execute tests
run: vendor/bin/phpunit

1
.gitignore vendored
View File

@ -1,6 +1,5 @@
build
composer.lock
docs
vendor
coverage
.phpunit.result.cache

View File

@ -1,21 +0,0 @@
language: php
php:
- 7.1
- 7.2
- 7.3
env:
matrix:
- COMPOSER_FLAGS="--prefer-lowest"
- COMPOSER_FLAGS=""
before_script:
- travis_retry composer self-update
- travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source
script:
- vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover
after_script:
- php vendor/bin/ocular code-coverage:upload --format=php-clover coverage.clover

View File

@ -2,6 +2,10 @@
All notable changes to `laravel-websockets` will be documented in this file
## 1.4.0 - 2020-03-03
- add support for Laravel 7
## 1.0.2 - 2018-12-06
- Fix issue with wrong namespaces

View File

@ -1,7 +1,7 @@
# Laravel WebSockets 🛰
[![Latest Version on Packagist](https://img.shields.io/packagist/v/beyondcode/laravel-websockets.svg?style=flat-square)](https://packagist.org/packages/beyondcode/laravel-websockets)
[![Build Status](https://img.shields.io/travis/beyondcode/laravel-websockets/master.svg?style=flat-square)](https://travis-ci.org/beyondcode/laravel-websockets)
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/beyondcode/laravel-websockets/run-tests?label=tests)
[![Quality Score](https://img.shields.io/scrutinizer/g/beyondcode/laravel-websockets.svg?style=flat-square)](https://scrutinizer-ci.com/g/beyondcode/laravel-websockets)
[![Total Downloads](https://img.shields.io/packagist/dt/beyondcode/laravel-websockets.svg?style=flat-square)](https://packagist.org/packages/beyondcode/laravel-websockets)

View File

@ -22,27 +22,27 @@
}
],
"require": {
"php": "^7.1",
"php": "^7.2",
"ext-json": "*",
"cboden/ratchet": "^0.4.1",
"clue/buzz-react": "^2.5",
"clue/redis-react": "^2.3",
"facade/ignition-contracts": "^1.0",
"guzzlehttp/psr7": "^1.5",
"illuminate/broadcasting": "5.7.* || 5.8.* || ^6.0",
"illuminate/console": "5.7.* || 5.8.* || ^6.0",
"illuminate/http": "5.7.* || 5.8.* || ^6.0",
"illuminate/routing": "5.7.* || 5.8.* || ^6.0",
"illuminate/support": "5.7.* || 5.8.* || ^6.0",
"pusher/pusher-php-server": "~3.0 || ~4.0",
"illuminate/broadcasting": "5.8.*|^6.0|^7.0",
"illuminate/console": "5.8.*|^6.0|^7.0",
"illuminate/http": "5.8.*|^6.0|^7.0",
"illuminate/routing": "5.8.*|^6.0|^7.0",
"illuminate/support": "5.8.*|^6.0|^7.0",
"pusher/pusher-php-server": "^3.0|^4.0",
"react/dns": "^1.1",
"symfony/http-kernel": "~4.0",
"symfony/psr-http-message-bridge": "^1.1"
"symfony/http-kernel": "^4.0|^5.0",
"symfony/psr-http-message-bridge": "^1.1|^2.0"
},
"require-dev": {
"mockery/mockery": "^1.2",
"orchestra/testbench": "3.7.* || 3.8.* || ^4.0",
"phpunit/phpunit": "^7.0 || ^8.0"
"mockery/mockery": "^1.3",
"orchestra/testbench": "3.8.*|^4.0|^5.0",
"phpunit/phpunit": "^8.0|^9.0"
},
"autoload": {
"psr-4": {

4
docs/_index.md Normal file
View File

@ -0,0 +1,4 @@
---
packageName: Laravel Websockets
githubUrl: https://github.com/beyondcode/laravel-websockets
---

View File

@ -0,0 +1,4 @@
---
title: Advanced Usage
order: 4
---

View File

@ -0,0 +1,104 @@
# Custom App Providers
With the multi-tenancy support of Laravel WebSockets, the default way of storing and retrieving the apps is by using the `websockets.php` config file.
Depending on your setup, you might have your app configuration stored elsewhere and having to keep the configuration in sync with your app storage can be tedious. To simplify this, you can create your own `AppProvider` class that will take care of retrieving the WebSocket credentials for a specific WebSocket application.
> Make sure that you do **not** perform any IO blocking tasks in your `AppProvider`, as they will interfere with the asynchronous WebSocket execution.
In order to create your custom `AppProvider`, create a class that implements the `BeyondCode\LaravelWebSockets\AppProviders\AppProvider` interface.
This is what it looks like:
```php
interface AppProvider
{
/** @return array[BeyondCode\LaravelWebSockets\AppProviders\App] */
public function all(): array;
/** @return BeyondCode\LaravelWebSockets\AppProviders\App */
public function findById($appId): ?App;
/** @return BeyondCode\LaravelWebSockets\AppProviders\App */
public function findByKey(string $appKey): ?App;
/** @return BeyondCode\LaravelWebSockets\AppProviders\App */
public function findBySecret(string $appSecret): ?App;
}
```
The following is an example AppProvider that utilizes an Eloquent model:
```php
namespace App\Providers;
use App\Application;
use BeyondCode\LaravelWebSockets\Apps\App;
use BeyondCode\LaravelWebSockets\Apps\AppProvider;
class MyCustomAppProvider implements AppProvider
{
public function all() : array
{
return Application::all()
->map(function($app) {
return $this->instanciate($app->toArray());
})
->toArray();
}
public function findById($appId) : ? App
{
return $this->instanciate(Application::findById($appId)->toArray());
}
public function findByKey(string $appKey) : ? App
{
return $this->instanciate(Application::findByKey($appKey)->toArray());
}
public function findBySecret(string $appSecret) : ? App
{
return $this->instanciate(Application::findBySecret($appSecret)->toArray());
}
protected function instanciate(?array $appAttributes) : ? App
{
if (!$appAttributes) {
return null;
}
$app = new App(
$appAttributes['id'],
$appAttributes['key'],
$appAttributes['secret']
);
if (isset($appAttributes['name'])) {
$app->setName($appAttributes['name']);
}
if (isset($appAttributes['host'])) {
$app->setHost($appAttributes['host']);
}
$app
->enableClientMessages($appAttributes['enable_client_messages'])
->enableStatistics($appAttributes['enable_statistics']);
return $app;
}
}
```
Once you have implemented your own AppProvider, you need to set it in the `websockets.php` configuration file:
```php
/**
* This class is responsible for finding the apps. The default provider
* will use the apps defined in this config file.
*
* You can create a custom provider by implementing the
* `AppProvider` interface.
*/
'app_provider' => MyCustomAppProvider::class,
```

View File

@ -0,0 +1,54 @@
# Custom WebSocket Handlers
While this package's main purpose is to make the usage of either the Pusher JavaScript client or Laravel Echo as easy as possible, you are not limited to the Pusher protocol at all.
There might be situations where all you need is a simple, bare-bone, WebSocket server where you want to have full control over the incoming payload and what you want to do with it - without having "channels" in the way.
You can easily create your own custom WebSocketHandler class. All you need to do is implement Ratchets `Ratchet\WebSocket\MessageComponentInterface`.
Once implemented, you will have a class that looks something like this:
```php
namespace App;
use Ratchet\ConnectionInterface;
use Ratchet\RFC6455\Messaging\MessageInterface;
use Ratchet\WebSocket\MessageComponentInterface;
class MyCustomWebSocketHandler implements MessageComponentInterface
{
public function onOpen(ConnectionInterface $connection)
{
// TODO: Implement onOpen() method.
}
public function onClose(ConnectionInterface $connection)
{
// TODO: Implement onClose() method.
}
public function onError(ConnectionInterface $connection, \Exception $e)
{
// TODO: Implement onError() method.
}
public function onMessage(ConnectionInterface $connection, MessageInterface $msg)
{
// TODO: Implement onMessage() method.
}
}
```
In the class itself you have full control over all the lifecycle events of your WebSocket connections and can intercept the incoming messages and react to them.
The only part missing is, that you will need to tell our WebSocket server to load this handler at a specific route endpoint. This can be achieved using the `WebSocketsRouter` facade.
This class takes care of registering the routes with the actual webSocket server. You can use the `webSocket` method to define a custom WebSocket endpoint. The method needs two arguments: the path where the WebSocket handled should be available and the fully qualified classname of the WebSocket handler class.
This could, for example, be done inside your `routes/web.php` file.
```php
WebSocketsRouter::webSocket('/my-websocket', \App\MyCustomWebSocketHandler::class);
```
Once you've added the custom WebSocket route, be sure to restart our WebSocket server for the changes to take place.

View File

@ -0,0 +1,4 @@
---
title: Basic Usage
order: 2
---

119
docs/basic-usage/pusher.md Normal file
View File

@ -0,0 +1,119 @@
---
title: Pusher Replacement
order: 1
---
# Pusher Replacement
The easiest way to get started with Laravel WebSockets is by using it as a [Pusher](https://pusher.com) replacement. The integrated WebSocket and HTTP Server has complete feature parity with the Pusher WebSocket and HTTP API. In addition to that, this package also ships with an easy to use debugging dashboard to see all incoming and outgoing WebSocket requests.
## Requirements
To make use of the Laravel WebSockets package in combination with Pusher, you first need to install the official Pusher PHP SDK.
If you are not yet familiar with the concept of Broadcasting in Laravel, please take a look at the [Laravel documentation](https://laravel.com/docs/6.0/broadcasting).
```bash
composer require pusher/pusher-php-server "~3.0"
```
Next, you should make sure to use Pusher as your broadcasting driver. This can be achieved by setting the `BROADCAST_DRIVER` environment variable in your `.env` file:
```
BROADCAST_DRIVER=pusher
```
## Pusher Configuration
When broadcasting events from your Laravel application to your WebSocket server, the default behavior is to send the event information to the official Pusher server. But since the Laravel WebSockets package comes with its own Pusher API implementation, we need to tell Laravel to send the events to our own server.
To do this, you should add the `host` and `port` configuration key to your `config/broadcasting.php` and add it to the `pusher` section. The default port of the Laravel WebSocket server is 6001.
```php
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => true,
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'http'
],
],
```
## Configuring WebSocket Apps
The Laravel WebSocket Pusher replacement server comes with multi-tenancy support out of the box. This means that you could host it independently from your current Laravel application and serve multiple WebSocket applications with one server.
To make the move from an existing Pusher setup to this package as easy as possible, the default app simply uses your existing Pusher configuration.
::: warning
Make sure to use the same app id, key and secret as in your broadcasting configuration section. Otherwise broadcasting events from Laravel will not work.
:::
::: tip
When using Laravel WebSockets as a Pusher replacement without having used Pusher before, it does not matter what you set as your `PUSHER_` variables. Just make sure they are unique for each project.
:::
You may add additional apps in your `config/websockets.php` file.
```php
'apps' => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'enable_client_messages' => false,
'enable_statistics' => true,
],
],
```
### Client Messages
For each app in your configuration file, you can define if this specific app should support a client-to-client messages. Usually all WebSocket messages go through your Laravel application before they will be broadcasted to other users. But sometimes you may want to enable a direct client-to-client communication instead of sending the events over the server. For example, a "typing" event in a chat application.
It is important that you apply additional care when using client messages, since these originate from other users, and could be subject to tampering by a malicious user of your site.
To enable or disable client messages, you can modify the `enable_client_messages` setting. The default value is `false`.
### Statistics
The Laravel WebSockets package comes with an out-of-the-box statistic solution that will give you key insights into the current status of your WebSocket server.
To enable or disable the statistics for one of your apps, you can modify the `enable_statistics` setting. The default value is `true`.
## Usage with Laravel Echo
The Laravel WebSockets package integrates nicely into [Laravel Echo](https://laravel.com/docs/6.0/broadcasting#receiving-broadcasts) to integrate into your frontend application and receive broadcasted events.
If you are new to Laravel Echo, be sure to take a look at the [official documentation](https://laravel.com/docs/6.0/broadcasting#receiving-broadcasts).
To make Laravel Echo work with Laravel WebSockets, you need to make some minor configuration changes when working with Laravel Echo. Add the `wsHost` and `wsPort` parameters and point them to your Laravel WebSocket server host and port.
By default, the Pusher JavaScript client tries to send statistic information - you should disable this using the `disableStats` option.
::: tip
When using Laravel WebSockets in combination with a custom SSL certificate, be sure to use the `encrypted` option and set it to `true`.
:::
```js
import Echo from "laravel-echo"
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
wsHost: window.location.hostname,
wsPort: 6001,
forceTLS: false,
disableStats: true,
});
```
Now you can use all Laravel Echo features in combination with Laravel WebSockets, such as [Presence Channels](https://laravel.com/docs/6.0/broadcasting#presence-channels), [Notifications](https://laravel.com/docs/6.0/broadcasting#notifications) and [Client Events](https://laravel.com/docs/6.0/broadcasting#client-events).

300
docs/basic-usage/ssl.md Normal file
View File

@ -0,0 +1,300 @@
---
title: SSL Support
order: 3
---
# SSL Support
Since most of the web's traffic is going through HTTPS, it's also crucial to secure your WebSocket server. Luckily, adding SSL support to this package is really simple.
## Configuration
The SSL configuration takes place in your `config/websockets.php` file.
The default configuration has a SSL section that looks like this:
```php
'ssl' => [
/*
* Path to local certificate file on filesystem. It must be a PEM encoded file which
* contains your certificate and private key. It can optionally contain the
* certificate chain of issuers. The private key also may be contained
* in a separate file specified by local_pk.
*/
'local_cert' => null,
/*
* Path to local private key file on filesystem in case of separate files for
* certificate (local_cert) and private key.
*/
'local_pk' => null,
/*
* Passphrase with which your local_cert file was encoded.
*/
'passphrase' => null
],
```
But this is only a subset of all the available configuration options.
This packages makes use of the official PHP [SSL context options](http://php.net/manual/en/context.ssl.php).
So if you find yourself in the need of adding additional configuration settings, take a look at the PHP documentation and simply add the configuration parameters that you need.
After setting up your SSL settings, you can simply (re)start your WebSocket server using:
```bash
php artisan websockets:serve
```
## Client configuration
When your SSL settings are in place and working, you still need to tell Laravel Echo that it should make use of it.
You can do this by specifying the `forceTLS` property in your JavaScript file, like this:
```js
import Echo from "laravel-echo"
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
wsHost: window.location.hostname,
wsPort: 6001,
disableStats: true,
forceTLS: true
});
```
## Server configuration
When broadcasting events from your Laravel application to the WebSocket server, you also need to tell Laravel to make use of HTTPS instead of HTTP. You can do this by setting the `scheme` option in your `config/broadcasting.php` file to `https`:
```php
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'https'
],
],
```
Since the SSL configuration can vary quite a lot, depending on your setup, let's take a look at the most common approaches.
## Usage with Laravel Valet
Laravel Valet uses self-signed SSL certificates locally.
To use self-signed certificates with Laravel WebSockets, here's how the SSL configuration section in your `config/websockets.php` file should look like.
::: tip
Make sure that you replace `YOUR-USERNAME` with your Mac username and `VALET-SITE.TLD` with the host of the Valet site that you're working on right now. For example `laravel-websockets-demo.test`.
:::
```php
'ssl' => [
/*
* Path to local certificate file on filesystem. It must be a PEM encoded file which
* contains your certificate and private key. It can optionally contain the
* certificate chain of issuers. The private key also may be contained
* in a separate file specified by local_pk.
*/
'local_cert' => '/Users/YOUR-USERNAME/.config/valet/Certificates/VALET-SITE.TLD.crt',
/*
* Path to local private key file on filesystem in case of separate files for
* certificate (local_cert) and private key.
*/
'local_pk' => '/Users/YOUR-USERNAME/.config/valet/Certificates/VALET-SITE.TLD.key',
/*
* Passphrase with which your local_cert file was encoded.
*/
'passphrase' => null,
'verify_peer' => false,
],
```
Next, you need to adjust the `config/broadcasting.php` file to make use of a secure connection when broadcasting messages from Laravel to the WebSocket server.
You also need to disable SSL verification.
```php
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'https',
'curl_options' => [
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
]
],
],
```
Last but not least, you still need to configure Laravel Echo to also use WSS on port 6001.
```js
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
wsHost: window.location.hostname,
wsPort: 6001,
wssPort: 6001,
disableStats: true,
});
```
## Usage with a reverse proxy (like Nginx)
Alternatively, you can also use a proxy service - like Nginx, HAProxy or Caddy - to handle the SSL configurations and proxy all requests in plain HTTP to your echo server.
A basic Nginx configuration would look like this, but you might want to tweak the SSL parameters to your liking.
```
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name socket.yourapp.tld;
# Start the SSL configurations
ssl on;
ssl_certificate /etc/letsencrypt/live/socket.yourapp.tld/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/socket.yourapp.tld/privkey.pem;
location / {
proxy_pass http://127.0.0.1:6001;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
# Allow the use of websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
```
You can now talk HTTPS to `socket.yourapp.tld`. You would configure your `config/broadcasting.php` like the example above, treating your socket server as an `https` endpoint.
### Same location for websockets and web contents
To have the websockets be served at the same location and port as your other web content, Nginx can be taught to map incoming requests based on their type to special sub-locations.
```
map $http_upgrade $type {
default "web";
websocket "ws";
}
server {
# Your default configuration comes here...
location / {
try_files /nonexistent @$type;
}
location @web {
try_files $uri $uri/ /index.php?$query_string;
}
location @ws {
proxy_pass http://127.0.0.1:6001;
proxy_set_header Host $host;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
# Allow the use of websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
```
This configuration is useful if you do not want to open multiple ports or you are restricted to which ports are already opened on your server. Alternatively, a second Nginx location can be used on the server-side, while the Pusher configuration [`wsPath`](https://github.com/pusher/pusher-js#wspath) can be used on the client-side (_note: `"pusher-js": ">=4.2.2"` is required for this configuration option_).
```
server {
# Your default configuration comes here...
location /ws {
proxy_pass http://127.0.0.1:6001;
proxy_set_header Host $host;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
# Allow the use of websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
```
### Nginx worker connections
Note that you might need to increase the amount of `worker_connections` in Nginx. Your WebSocket connections will now be sent to Nginx, which in turn will send those along to the websocket server.
By default, that will have a sane limit of 1024 connections. If you are expecting more concurrent connections to your WebSockets, you can increase this in your global `nginx.conf`.
```
events {
worker_connections 1024;
}
```
You know you've reached this limit of your Nginx error logs contain similar messages to these:
```
[alert] 1024 worker_connections are not enough while connecting to upstream
```
Remember to restart your Nginx after you've modified the `worker_connections`.
### Example using Caddy
[Caddy](https://caddyserver.com) can also be used to automatically obtain a TLS certificate from Let's Encrypt and terminate TLS before proxying to your echo server.
An example configuration would look like this:
```
socket.yourapp.tld {
rewrite / {
if {>Connection} has Upgrade
if {>Upgrade} is websocket
to /websocket-proxy/{path}?{query}
}
proxy /websocket-proxy 127.0.0.1:6001 {
without /special-websocket-url
transparent
websocket
}
tls youremail.com
}
```
Note the `to /websocket-proxy`, this is a dummy path to allow the `proxy` directive to only proxy on websocket connections. This should be a path that will never be used by your application's routing. Also, note that you should change `127.0.0.1` to the hostname of your websocket server. For example, if you're running in a Docker environment, this might be the container name of your websocket server.

View File

@ -0,0 +1,80 @@
---
title: Starting the WebSocket server
order: 2
---
# Starting the WebSocket server
Once you have configured your WebSocket apps and Pusher settings, you can start the Laravel WebSocket server by issuing the artisan command:
```bash
php artisan websockets:serve
```
## Using a different port
The default port of the Laravel WebSocket server is `6001`. You may pass a different port to the command using the `--port` option.
```bash
php artisan websockets:serve --port=3030
```
This will start listening on port `3030`.
## Restricting the listening host
By default, the Laravel WebSocket server will listen on `0.0.0.0` and will allow incoming connections from all networks. If you want to restrict this, you can start the server with a `--host` option, followed by an IP.
For example, by using `127.0.0.1`, you will only allow WebSocket connections from localhost.
```bash
php artisan websockets:serve --host=127.0.0.1
```
## Keeping the socket server running with supervisord
The `websockets:serve` daemon needs to always be running in order to accept connections. This is a prime use case for `supervisor`, a task runner on Linux.
First, make sure `supervisor` is installed.
```bash
# On Debian / Ubuntu
apt install supervisor
# On Red Hat / CentOS
yum install supervisor
systemctl enable supervisord
```
Once installed, add a new process that `supervisor` needs to keep running. You place your configurations in the `/etc/supervisor/conf.d` (Debian/Ubuntu) or `/etc/supervisord.d` (Red Hat/CentOS) directory.
Within that directory, create a new file called `websockets.conf`.
```bash
[program:websockets]
command=/usr/bin/php /home/laravel-echo/laravel-websockets/artisan websockets:serve
numprocs=1
autostart=true
autorestart=true
user=laravel-echo
```
Once created, instruct `supervisor` to reload its configuration files (without impacting the already running `supervisor` jobs).
```bash
supervisorctl update
supervisorctl start websockets
```
Your echo server should now be running (you can verify this with `supervisorctl status`). If it were to crash, `supervisor` will automatically restart it.
Please note that, by default, `supervisor` will force a maximum number of open files onto all the processes that it manages. This is configured by the `minfds` parameter in `supervisord.conf`.
If you want to increase the maximum number of open files, you may do so in `/etc/supervisor/supervisord.conf` (Debian/Ubuntu) or `/etc/supervisord.conf` (Red Hat/CentOS):
```
[supervisord]
minfds=10240; (min. avail startup file descriptors;default 1024)
```
After changing this setting, you'll need to restart the supervisor process (which in turn will restart all your processes that it manages).

4
docs/debugging/_index.md Normal file
View File

@ -0,0 +1,4 @@
---
title: Debugging
order: 3
---

10
docs/debugging/console.md Normal file
View File

@ -0,0 +1,10 @@
---
title: Console Logging
order: 1
---
# Console Logging
When you start the Laravel WebSocket server and your application is in debug mode, you will automatically see all incoming and outgoing WebSocket events in your terminal.
![Console Logging](/img/console.png)

View File

@ -0,0 +1,74 @@
---
title: Debug Dashboard
order: 2
---
# Debug Dashboard
In addition to logging the events to the console, you can also use a real-time dashboard that shows you all incoming connections, events and disconnects the moment they happen on your WebSocket server.
![Debug Dashboard](/img/dashboard.jpg)
## Accessing the Dashboard
The default location of the WebSocket dashboard is at `/laravel-websockets`. The routes get automatically registered.
If you want to change the URL of the dashboard, you can configure it with the `path` setting in your `config/websockets.php` file.
To access the debug dashboard, you can visit the dashboard URL of your Laravel project in the browser.
Since your WebSocket server has support for multiple apps, you can select which app you want to connect to and inspect.
By pressing the "Connect" button, you can establish the WebSocket connection and see all events taking place on your WebSocket server from there on in real-time.
**Note:** Be sure to set the ``APP_URL`` env variable to match the current URL where your project is running to be sure the stats graph works properly.
## Protecting the Dashboard
By default, access to the WebSocket dashboard is only allowed while your application environment is set to `local`.
However, you can change this behavior by overriding the Laravel Gate being used. A good place for this is the `AuthServiceProvider` that ships with Laravel.
```php
public function boot()
{
$this->registerPolicies();
Gate::define('viewWebSocketsDashboard', function ($user = null) {
return in_array($user->email, [
//
]);
});
}
```
## Statistics
This package allows you to record key metrics of your WebSocket server. The WebSocket server will store a snapshot of the current number of peak connections, the amount of received WebSocket messages and the amount of received API messages defined in a fixed interval. The default setting is to store a snapshot every 60 seconds.
In addition to simply storing the statistic information in your database, you can also see the statistics as they happen in real-time on the debug dashboard.
![Real-Time Statistics](/img/statistics.gif)
You can modify this interval by changing the `interval_in_seconds` setting in your config file.
## Cleanup old Statistics
After using the WebSocket server for a while you will have recorded a lot of statistical data that you might no longer need. This package provides an artisan command `websockets:clean` to clean these statistic log entries.
Running this command will result in the deletion of all recorded statistics that are older than the number of days specified in the `delete_statistics_older_than_days` setting of the config file.
You can leverage Laravel's scheduler to run the clean up command now and then.
```php
//app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->command('websockets:clean')->daily();
}
```
## Event Creator
The dashboard also comes with an easy-to-use event creator, that lets you manually send events to your channels.
Simply enter the channel, the event name and provide a valid JSON payload to send it to all connected clients in the given channel.

4
docs/faq/_index.md Normal file
View File

@ -0,0 +1,4 @@
---
title: FAQ
order: 5
---

48
docs/faq/deploying.md Normal file
View File

@ -0,0 +1,48 @@
---
title: Deploying
order: 1
---
# Deploying
When your application is ready to get deployed, here are some tips to improve your WebSocket server.
### Open Connection Limit
On Unix systems, every user that connects to your WebSocket server is represented as a file somewhere on the system.
As a security measurement of every Unix based OS, the number of "file descriptors" an application may have open at a time is limited - most of the time to a default value of 1024 - which would result in a maximum number of 1024 concurrent users on your WebSocket server.
In addition to the OS restrictions, this package makes use of an event loop called "stream_select", which has a hard limit of 1024.
#### Increasing the maximum number of file descriptors
The operating system limit of open "file descriptors" can be increased using the `ulimit` command. The `-n` option modifies the number of open file descriptors.
```bash
ulimit -n 10000
```
The `ulimit` command only **temporarily** increases the maximum number of open file descriptors. To permanently modify this value, you can edit it in your operating system `limits.conf` file.
You are best to do so by creating a file in the `limits.d` directory. This will work for both Red Hat & Ubuntu derivatives.
```bash
$ cat /etc/security/limits.d/laravel-echo.conf
laravel-echo soft nofile 10000
```
The above example assumes you will run your echo server as the `laravel-echo` user, you are free to change that to your liking.
#### Changing the event loop
To make use of a different event loop, that does not have a hard limit of 1024 concurrent connections, you can either install the `ev` or `event` PECL extension using:
```bash
sudo pecl install ev
# or
sudo pecl install event
```
#### Deploying on Laravel Forge
If your are using [Laravel Forge](https://forge.laravel.com/) for the deployment [this article by Alex Bouma](https://alex.bouma.dev/installing-laravel-websockets-on-forge) might help you out.

18
docs/faq/scaling.md Normal file
View File

@ -0,0 +1,18 @@
---
title: ... but does it scale?
order: 2
---
# ... but does it scale?
Of course, this is not a question with an easy answer as your mileage may vary. But with the appropriate server-side configuration your WebSocket server can easily hold a **lot** of concurrent connections.
This is an example benchmark that was done on the smallest Digital Ocean droplet, that also had a couple of other Laravel projects running. On this specific server, the maximum number of **concurrent** connections ended up being ~15,000.
![Benchmark](/img/simultaneous_users.png)
Here is another benchmark that was run on a 2GB Digital Ocean droplet with 2 CPUs. The maximum number of **concurrent** connections on this server setup is nearly 60,000.
![Benchmark](/img/simultaneous_users_2gb.png)
Make sure to take a look at the [Deployment Tips](/docs/laravel-websockets/faq/deploying) to find out how to improve your specific setup.

View File

@ -0,0 +1,4 @@
---
title: Getting Started
order: 1
---

View File

@ -0,0 +1,135 @@
---
title: Installation
order: 2
---
# Installation
Laravel WebSockets can be installed via composer:
```bash
composer require beyondcode/laravel-websockets
```
The package will automatically register a service provider.
This package comes with a migration to store statistic information while running your WebSocket server. You can publish the migration file using:
```bash
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
```
Run the migrations with:
```bash
php artisan migrate
```
Next, you need to publish the WebSocket configuration file:
```bash
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
```
This is the default content of the config file that will be published as `config/websockets.php`:
```php
return [
/*
* This package comes with multi tenancy out of the box. Here you can
* configure the different apps that can use the webSockets server.
*
* Optionally you can disable client events so clients cannot send
* messages to each other via the webSockets.
*/
'apps' => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'enable_client_messages' => false,
'enable_statistics' => true,
],
],
/*
* This class is responsible for finding the apps. The default provider
* will use the apps defined in this config file.
*
* You can create a custom provider by implementing the
* `AppProvider` interface.
*/
'app_provider' => BeyondCode\LaravelWebSockets\Apps\ConfigAppProvider::class,
/*
* This array contains the hosts of which you want to allow incoming requests.
* Leave this empty if you want to accept requests from all hosts.
*/
'allowed_origins' => [
//
],
/*
* The maximum request size in kilobytes that is allowed for an incoming WebSocket request.
*/
'max_request_size_in_kb' => 250,
/*
* This path will be used to register the necessary routes for the package.
*/
'path' => 'laravel-websockets',
'statistics' => [
/*
* This model will be used to store the statistics of the WebSocketsServer.
* The only requirement is that the model should extend
* `WebSocketsStatisticsEntry` provided by this package.
*/
'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,
/*
* Here you can specify the interval in seconds at which statistics should be logged.
*/
'interval_in_seconds' => 60,
/*
* When the clean-command is executed, all recorded statistics older than
* the number of days specified here will be deleted.
*/
'delete_statistics_older_than_days' => 60,
/*
* Use an DNS resolver to make the requests to the statistics logger
* default is to resolve everything to 127.0.0.1.
*/
'perform_dns_lookup' => false,
],
/*
* Define the optional SSL context for your WebSocket connections.
* You can see all available options at: http://php.net/manual/en/context.ssl.php
*/
'ssl' => [
/*
* Path to local certificate file on filesystem. It must be a PEM encoded file which
* contains your certificate and private key. It can optionally contain the
* certificate chain of issuers. The private key also may be contained
* in a separate file specified by local_pk.
*/
'local_cert' => null,
/*
* Path to local private key file on filesystem in case of separate files for
* certificate (local_cert) and private key.
*/
'local_pk' => null,
/*
* Passphrase for your local_cert file.
*/
'passphrase' => null
],
];
```

View File

@ -0,0 +1,21 @@
---
title: Introduction
order: 1
---
# Laravel WebSockets 🛰
WebSockets for Laravel. Done right.
Laravel WebSockets is a package for Laravel 5.7 and up that will get your application started with WebSockets in no-time! It has a drop-in Pusher API replacement, has a debug dashboard, realtime statistics and even allows you to create custom WebSocket controllers.
Once installed, you can start it with one simple command:
```php
php artisan websockets:serve
```
---
If you want to know how all of it works under the hood, we wrote an in-depth [blogpost](https://murze.be/introducing-laravel-websockets-an-easy-to-use-websocket-server-implemented-in-php) about it.
To help you get started, you can also take a look at the [demo repository](https://github.com/beyondcode/laravel-websockets-demo), that implements a basic Chat built with this package.

View File

@ -0,0 +1,10 @@
---
title: Questions and issues
order: 3
---
# Questions and issues
Find yourself stuck using the package? Found a bug? Do you have general questions or suggestions for improving laravel-websockets? Feel free to create an issue on [GitHub](https://github.com/beyondcode/laravel-websockets/issues), we'll try to address it as soon as possible.
If you've found a bug regarding security please mail [marcel@beyondco.de](mailto:marcel@beyondco.de) instead of using the issue tracker.

View File

@ -19,12 +19,6 @@
<directory suffix=".php">src/</directory>
</whitelist>
</filter>
<logging>
<log type="tap" target="build/report.tap"/>
<log type="junit" target="build/report.junit.xml"/>
<log type="coverage-text" target="build/coverage.txt"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
<php>
<env name="DB_CONNECTION" value="testing"/>
</php>

View File

@ -21,6 +21,9 @@ class App
/** @var string|null */
public $host;
/** @var string|null */
public $path;
/** @var int|null */
public $capacity = null;
@ -76,6 +79,13 @@ class App
return $this;
}
public function setPath(string $path)
{
$this->path = $path;
return $this;
}
public function enableClientMessages(bool $enabled = true)
{
$this->clientMessagesEnabled = $enabled;

View File

@ -71,6 +71,10 @@ class ConfigAppProvider implements AppProvider
$app->setHost($appAttributes['host']);
}
if (isset($appAttributes['path'])) {
$app->setPath($appAttributes['path']);
}
$app
->enableClientMessages($appAttributes['enable_client_messages'])
->enableStatistics($appAttributes['enable_statistics'])

View File

@ -2,24 +2,24 @@
namespace BeyondCode\LaravelWebSockets\Console;
use React\Socket\Connector;
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
use BeyondCode\LaravelWebSockets\Facades\WebSocketsRouter;
use BeyondCode\LaravelWebSockets\PubSub\ReplicationInterface;
use BeyondCode\LaravelWebSockets\Server\Logger\ConnectionLogger;
use BeyondCode\LaravelWebSockets\Server\Logger\HttpLogger;
use BeyondCode\LaravelWebSockets\Server\Logger\WebsocketsLogger;
use BeyondCode\LaravelWebSockets\Server\WebSocketServerFactory;
use BeyondCode\LaravelWebSockets\Statistics\DnsResolver;
use BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger;
use BeyondCode\LaravelWebSockets\Statistics\Logger\StatisticsLogger as StatisticsLoggerInterface;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use Clue\React\Buzz\Browser;
use Illuminate\Console\Command;
use React\Dns\Config\Config as DnsConfig;
use React\Dns\Resolver\Factory as DnsFactory;
use React\Dns\Resolver\ResolverInterface;
use React\EventLoop\Factory as LoopFactory;
use React\Dns\Resolver\Factory as DnsFactory;
use BeyondCode\LaravelWebSockets\Statistics\DnsResolver;
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
use BeyondCode\LaravelWebSockets\Facades\WebSocketsRouter;
use BeyondCode\LaravelWebSockets\Server\Logger\HttpLogger;
use BeyondCode\LaravelWebSockets\PubSub\ReplicationInterface;
use BeyondCode\LaravelWebSockets\Server\WebSocketServerFactory;
use BeyondCode\LaravelWebSockets\Server\Logger\ConnectionLogger;
use BeyondCode\LaravelWebSockets\Server\Logger\WebsocketsLogger;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger;
use BeyondCode\LaravelWebSockets\Statistics\Logger\StatisticsLogger as StatisticsLoggerInterface;
use React\Socket\Connector;
class StartWebSocketServer extends Command
{

View File

@ -2,9 +2,9 @@
namespace BeyondCode\LaravelWebSockets\Dashboard;
use stdClass;
use Ratchet\ConnectionInterface;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use Ratchet\ConnectionInterface;
use stdClass;
class DashboardLogger
{

View File

@ -2,10 +2,10 @@
namespace BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers;
use Pusher\Pusher;
use Illuminate\Http\Request;
use BeyondCode\LaravelWebSockets\Apps\App;
use Illuminate\Broadcasting\Broadcasters\PusherBroadcaster;
use Illuminate\Http\Request;
use Pusher\Pusher;
class AuthenticateDashboard
{

View File

@ -2,10 +2,10 @@
namespace BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers;
use Pusher\Pusher;
use Illuminate\Http\Request;
use BeyondCode\LaravelWebSockets\Statistics\Rules\AppId;
use Illuminate\Broadcasting\Broadcasters\PusherBroadcaster;
use Illuminate\Http\Request;
use Pusher\Pusher;
class SendMessage
{

View File

@ -2,8 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers;
use Illuminate\Http\Request;
use BeyondCode\LaravelWebSockets\Apps\AppProvider;
use Illuminate\Http\Request;
class ShowDashboard
{

View File

@ -3,9 +3,9 @@
namespace BeyondCode\LaravelWebSockets\Exceptions;
use Exception;
use Facade\IgnitionContracts\Solution;
use Facade\IgnitionContracts\BaseSolution;
use Facade\IgnitionContracts\ProvidesSolution;
use Facade\IgnitionContracts\Solution;
class InvalidApp extends Exception implements ProvidesSolution
{

View File

@ -2,8 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Facades;
use Illuminate\Support\Facades\Facade;
use BeyondCode\LaravelWebSockets\Statistics\Logger\StatisticsLogger as StatisticsLoggerInterface;
use Illuminate\Support\Facades\Facade;
/**
* @see \BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger

View File

@ -2,23 +2,23 @@
namespace BeyondCode\LaravelWebSockets\HttpApi\Controllers;
use Exception;
use Pusher\Pusher;
use Illuminate\Support\Arr;
use Illuminate\Http\Request;
use GuzzleHttp\Psr7\Response;
use Ratchet\ConnectionInterface;
use Illuminate\Http\JsonResponse;
use GuzzleHttp\Psr7\ServerRequest;
use Illuminate\Support\Collection;
use React\Promise\PromiseInterface;
use Ratchet\Http\HttpServerInterface;
use Psr\Http\Message\RequestInterface;
use BeyondCode\LaravelWebSockets\Apps\App;
use BeyondCode\LaravelWebSockets\QueryParameters;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use Exception;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\ServerRequest;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Psr\Http\Message\RequestInterface;
use Pusher\Pusher;
use Ratchet\ConnectionInterface;
use Ratchet\Http\HttpServerInterface;
use React\Promise\PromiseInterface;
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
use Symfony\Component\HttpKernel\Exception\HttpException;
abstract class Controller implements HttpServerInterface
{

View File

@ -2,9 +2,9 @@
namespace BeyondCode\LaravelWebSockets\HttpApi\Controllers;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Symfony\Component\HttpKernel\Exception\HttpException;
use BeyondCode\LaravelWebSockets\PubSub\ReplicationInterface;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;

View File

@ -2,10 +2,10 @@
namespace BeyondCode\LaravelWebSockets\HttpApi\Controllers;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PresenceChannel;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Symfony\Component\HttpKernel\Exception\HttpException;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PresenceChannel;
class FetchUsersController extends Controller
{

View File

@ -2,9 +2,9 @@
namespace BeyondCode\LaravelWebSockets\HttpApi\Controllers;
use Illuminate\Http\Request;
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger;
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
use Illuminate\Http\Request;
class TriggerEventController extends Controller
{

View File

@ -2,8 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Server\Logger;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Output\OutputInterface;
class Logger
{

View File

@ -2,11 +2,11 @@
namespace BeyondCode\LaravelWebSockets\Server\Logger;
use BeyondCode\LaravelWebSockets\QueryParameters;
use Exception;
use Ratchet\ConnectionInterface;
use Ratchet\RFC6455\Messaging\MessageInterface;
use Ratchet\WebSocket\MessageComponentInterface;
use BeyondCode\LaravelWebSockets\QueryParameters;
class WebsocketsLogger extends Logger implements MessageComponentInterface
{

View File

@ -2,10 +2,10 @@
namespace BeyondCode\LaravelWebSockets\Server;
use Psr\Http\Message\RequestInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Http\CloseResponseTrait;
use Ratchet\Http\HttpServerInterface;
use Psr\Http\Message\RequestInterface;
use Ratchet\MessageComponentInterface;
class OriginCheck implements HttpServerInterface

View File

@ -2,18 +2,18 @@
namespace BeyondCode\LaravelWebSockets\Server;
use Ratchet\WebSocket\WsServer;
use BeyondCode\LaravelWebSockets\Exceptions\InvalidWebSocketController;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchChannelController;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchChannelsController;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchUsersController;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\TriggerEventController;
use BeyondCode\LaravelWebSockets\Server\Logger\WebsocketsLogger;
use BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler;
use Illuminate\Support\Collection;
use Ratchet\WebSocket\MessageComponentInterface;
use Ratchet\WebSocket\WsServer;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Ratchet\WebSocket\MessageComponentInterface;
use BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler;
use BeyondCode\LaravelWebSockets\Server\Logger\WebsocketsLogger;
use BeyondCode\LaravelWebSockets\Exceptions\InvalidWebSocketController;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchUsersController;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchChannelController;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\TriggerEventController;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchChannelsController;
class Router
{

View File

@ -2,17 +2,17 @@
namespace BeyondCode\LaravelWebSockets\Server;
use BeyondCode\LaravelWebSockets\Server\Logger\HttpLogger;
use Ratchet\Http\Router;
use React\Socket\Server;
use Ratchet\Server\IoServer;
use React\Socket\SecureServer;
use React\EventLoop\LoopInterface;
use React\EventLoop\Factory as LoopFactory;
use React\EventLoop\LoopInterface;
use React\Socket\SecureServer;
use React\Socket\Server;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Console\Output\OutputInterface;
use BeyondCode\LaravelWebSockets\Server\Logger\HttpLogger;
class WebSocketServerFactory
{

View File

@ -2,8 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Statistics;
use React\Promise\FulfilledPromise;
use React\Dns\Resolver\ResolverInterface;
use React\Promise\FulfilledPromise;
class DnsResolver implements ResolverInterface
{

View File

@ -2,12 +2,12 @@
namespace BeyondCode\LaravelWebSockets\Statistics\Events;
use Illuminate\Support\Str;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger;
use BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Str;
class StatisticsUpdated implements ShouldBroadcast
{

View File

@ -2,9 +2,9 @@
namespace BeyondCode\LaravelWebSockets\Statistics\Http\Controllers;
use Illuminate\Http\Request;
use BeyondCode\LaravelWebSockets\Statistics\Rules\AppId;
use BeyondCode\LaravelWebSockets\Statistics\Events\StatisticsUpdated;
use BeyondCode\LaravelWebSockets\Statistics\Rules\AppId;
use Illuminate\Http\Request;
class WebSocketStatisticsEntriesController
{

View File

@ -2,13 +2,13 @@
namespace BeyondCode\LaravelWebSockets\Statistics\Logger;
use Clue\React\Buzz\Browser;
use Ratchet\ConnectionInterface;
use function GuzzleHttp\Psr7\stream_for;
use BeyondCode\LaravelWebSockets\Apps\App;
use BeyondCode\LaravelWebSockets\Statistics\Http\Controllers\WebSocketStatisticsEntriesController;
use BeyondCode\LaravelWebSockets\Statistics\Statistic;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use BeyondCode\LaravelWebSockets\Statistics\Http\Controllers\WebSocketStatisticsEntriesController;
use Clue\React\Buzz\Browser;
use function GuzzleHttp\Psr7\stream_for;
use Ratchet\ConnectionInterface;
class HttpStatisticsLogger implements StatisticsLogger
{

View File

@ -2,8 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Statistics\Rules;
use Illuminate\Contracts\Validation\Rule;
use BeyondCode\LaravelWebSockets\Apps\AppProvider;
use Illuminate\Contracts\Validation\Rule;
class AppId implements Rule
{

View File

@ -2,12 +2,12 @@
namespace BeyondCode\LaravelWebSockets\WebSockets\Channels;
use stdClass;
use Illuminate\Support\Str;
use Ratchet\ConnectionInterface;
use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger;
use BeyondCode\LaravelWebSockets\PubSub\ReplicationInterface;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature;
use Illuminate\Support\Str;
use Ratchet\ConnectionInterface;
use stdClass;
class Channel
{

View File

@ -2,13 +2,13 @@
namespace BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\Channel;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PresenceChannel;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PrivateChannel;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Ratchet\ConnectionInterface;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\Channel;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PrivateChannel;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PresenceChannel;
class ArrayChannelManager implements ChannelManager
{

View File

@ -2,10 +2,10 @@
namespace BeyondCode\LaravelWebSockets\WebSockets\Channels;
use stdClass;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature;
use Ratchet\ConnectionInterface;
use React\Promise\PromiseInterface;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature;
use stdClass;
class PresenceChannel extends Channel
{

View File

@ -2,9 +2,9 @@
namespace BeyondCode\LaravelWebSockets\WebSockets\Channels;
use stdClass;
use Ratchet\ConnectionInterface;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature;
use Ratchet\ConnectionInterface;
use stdClass;
class PrivateChannel extends Channel
{

View File

@ -2,10 +2,10 @@
namespace BeyondCode\LaravelWebSockets\WebSockets\Messages;
use stdClass;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use Illuminate\Support\Str;
use Ratchet\ConnectionInterface;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use stdClass;
class PusherChannelProtocolMessage implements PusherMessage
{

View File

@ -2,11 +2,11 @@
namespace BeyondCode\LaravelWebSockets\WebSockets\Messages;
use stdClass;
use Illuminate\Support\Str;
use Ratchet\ConnectionInterface;
use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use Illuminate\Support\Str;
use Ratchet\ConnectionInterface;
use stdClass;
class PusherClientMessage implements PusherMessage
{

View File

@ -2,10 +2,10 @@
namespace BeyondCode\LaravelWebSockets\WebSockets\Messages;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use Illuminate\Support\Str;
use Ratchet\ConnectionInterface;
use Ratchet\RFC6455\Messaging\MessageInterface;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
class PusherMessageFactory
{

View File

@ -2,19 +2,19 @@
namespace BeyondCode\LaravelWebSockets\WebSockets;
use Exception;
use Ratchet\ConnectionInterface;
use BeyondCode\LaravelWebSockets\Apps\App;
use Ratchet\RFC6455\Messaging\MessageInterface;
use Ratchet\WebSocket\MessageComponentInterface;
use BeyondCode\LaravelWebSockets\QueryParameters;
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger;
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
use BeyondCode\LaravelWebSockets\QueryParameters;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\ConnectionsOverCapacity;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\UnknownAppKey;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\WebSocketException;
use BeyondCode\LaravelWebSockets\WebSockets\Messages\PusherMessageFactory;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\ConnectionsOverCapacity;
use Exception;
use Ratchet\ConnectionInterface;
use Ratchet\RFC6455\Messaging\MessageInterface;
use Ratchet\WebSocket\MessageComponentInterface;
class WebSocketHandler implements MessageComponentInterface
{

View File

@ -2,27 +2,29 @@
namespace BeyondCode\LaravelWebSockets;
use BeyondCode\LaravelWebSockets\Apps\AppProvider;
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\AuthenticateDashboard;
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\DashboardApiController;
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\SendMessage;
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\ShowDashboard;
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize as AuthorizeDashboard;
use BeyondCode\LaravelWebSockets\PubSub\Broadcasters\RedisPusherBroadcaster;
use BeyondCode\LaravelWebSockets\PubSub\Drivers\LocalClient;
use BeyondCode\LaravelWebSockets\PubSub\Drivers\RedisClient;
use BeyondCode\LaravelWebSockets\PubSub\ReplicationInterface;
use BeyondCode\LaravelWebSockets\Server\Router;
use BeyondCode\LaravelWebSockets\Statistics\Http\Controllers\WebSocketStatisticsEntriesController;
use BeyondCode\LaravelWebSockets\Statistics\Http\Middleware\Authorize as AuthorizeStatistics;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager;
use Pusher\Pusher;
use Psr\Log\LoggerInterface;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;
use Illuminate\Broadcasting\BroadcastManager;
use BeyondCode\LaravelWebSockets\Server\Router;
use BeyondCode\LaravelWebSockets\Apps\AppProvider;
use BeyondCode\LaravelWebSockets\PubSub\Drivers\LocalClient;
use BeyondCode\LaravelWebSockets\PubSub\Drivers\RedisClient;
use BeyondCode\LaravelWebSockets\PubSub\ReplicationInterface;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\SendMessage;
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\ShowDashboard;
use BeyondCode\LaravelWebSockets\PubSub\Broadcasters\RedisPusherBroadcaster;
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\AuthenticateDashboard;
use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\DashboardApiController;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager;
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize as AuthorizeDashboard;
use BeyondCode\LaravelWebSockets\Statistics\Http\Middleware\Authorize as AuthorizeStatistics;
use BeyondCode\LaravelWebSockets\Statistics\Http\Controllers\WebSocketStatisticsEntriesController;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
class WebSocketsServiceProvider extends ServiceProvider
{
@ -32,7 +34,7 @@ class WebSocketsServiceProvider extends ServiceProvider
__DIR__.'/../config/websockets.php' => base_path('config/websockets.php'),
], 'config');
if (! class_exists('CreateWebSocketsStatisticsEntries')) {
if (! Schema::hasTable('websockets_statistics_entries')) {
$this->publishes([
__DIR__.'/../database/migrations/create_websockets_statistics_entries_table.php.stub' => database_path('migrations/'.date('Y_m_d_His', time()).'_create_websockets_statistics_entries_table.php'),
], 'migrations');

View File

@ -2,8 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Tests\Channels;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
class ChannelTest extends TestCase
{

View File

@ -2,8 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Tests\Channels;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature;
class PresenceChannelTest extends TestCase

View File

@ -2,8 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Tests\Channels;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature;
class PrivateChannelTest extends TestCase

View File

@ -3,8 +3,8 @@
namespace BeyondCode\LaravelWebSockets\Tests\ClientProviders;
use BeyondCode\LaravelWebSockets\Apps\App;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Exceptions\InvalidApp;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
class AppTest extends TestCase
{

View File

@ -2,8 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Tests\ClientProviders;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Apps\ConfigAppProvider;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
class ConfigAppProviderTest extends TestCase
{

View File

@ -3,10 +3,10 @@
namespace BeyondCode\LaravelWebSockets\Tests\Commands;
use Artisan;
use BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry;
class CleanStatisticsTest extends TestCase
{

View File

@ -4,8 +4,8 @@ namespace BeyondCode\LaravelWebSockets\Tests;
use BeyondCode\LaravelWebSockets\Apps\App;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\UnknownAppKey;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\ConnectionsOverCapacity;
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\UnknownAppKey;
class ConnectionTest extends TestCase
{

View File

@ -2,13 +2,13 @@
namespace BeyondCode\LaravelWebSockets\Tests\HttpApi;
use Pusher\Pusher;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchChannelController;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Connection;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use GuzzleHttp\Psr7\Request;
use Illuminate\Http\JsonResponse;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Connection;
use Pusher\Pusher;
use Symfony\Component\HttpKernel\Exception\HttpException;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchChannelController;
class FetchChannelTest extends TestCase
{

View File

@ -2,13 +2,13 @@
namespace BeyondCode\LaravelWebSockets\Tests\HttpApi;
use Pusher\Pusher;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchChannelsController;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Connection;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use GuzzleHttp\Psr7\Request;
use Illuminate\Http\JsonResponse;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Connection;
use Pusher\Pusher;
use Symfony\Component\HttpKernel\Exception\HttpException;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchChannelsController;
class FetchChannelsTest extends TestCase
{

View File

@ -2,12 +2,12 @@
namespace BeyondCode\LaravelWebSockets\Tests\HttpApi;
use Pusher\Pusher;
use GuzzleHttp\Psr7\Request;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Connection;
use Symfony\Component\HttpKernel\Exception\HttpException;
use BeyondCode\LaravelWebSockets\HttpApi\Controllers\FetchUsersController;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Connection;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use GuzzleHttp\Psr7\Request;
use Pusher\Pusher;
use Symfony\Component\HttpKernel\Exception\HttpException;
class FetchUsersTest extends TestCase
{

View File

@ -2,8 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Tests\Messages;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
class PusherClientMessageTest extends TestCase
{

View File

@ -3,8 +3,8 @@
namespace BeyondCode\LaravelWebSockets\Tests\Mocks;
use GuzzleHttp\Psr7\Request;
use Ratchet\ConnectionInterface;
use PHPUnit\Framework\Assert as PHPUnit;
use Ratchet\ConnectionInterface;
class Connection implements ConnectionInterface
{

View File

@ -2,9 +2,9 @@
namespace BeyondCode\LaravelWebSockets\Tests\Statistics\Controllers;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry;
use BeyondCode\LaravelWebSockets\Statistics\Http\Controllers\WebSocketStatisticsEntriesController;
use BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
class WebSocketsStatisticsControllerTest extends TestCase
{
@ -23,6 +23,7 @@ class WebSocketsStatisticsControllerTest extends TestCase
$this->assertCount(1, $entries);
$actual = $entries->first()->attributesToArray();
foreach ($this->payload() as $key => $value) {
$this->assertArrayHasKey($key, $actual);
$this->assertSame($value, $actual[$key]);

View File

@ -2,8 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Tests\Statistics\Controllers;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
class StatisticsLoggerTest extends TestCase
{

View File

@ -2,8 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Tests\Statistics\Rules;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
use BeyondCode\LaravelWebSockets\Statistics\Rules\AppId;
use BeyondCode\LaravelWebSockets\Tests\TestCase;
class AppIdTest extends TestCase
{

View File

@ -2,17 +2,17 @@
namespace BeyondCode\LaravelWebSockets\Tests;
use Mockery;
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Connection;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
use BeyondCode\LaravelWebSockets\Tests\Statistics\Logger\FakeStatisticsLogger;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler;
use BeyondCode\LaravelWebSockets\WebSocketsServiceProvider;
use Clue\React\Buzz\Browser;
use GuzzleHttp\Psr7\Request;
use Mockery;
use Ratchet\ConnectionInterface;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Message;
use BeyondCode\LaravelWebSockets\Tests\Mocks\Connection;
use BeyondCode\LaravelWebSockets\Facades\StatisticsLogger;
use BeyondCode\LaravelWebSockets\WebSocketsServiceProvider;
use BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use BeyondCode\LaravelWebSockets\Tests\Statistics\Logger\FakeStatisticsLogger;
abstract class TestCase extends \Orchestra\Testbench\TestCase
{