I’m trying to add websockets support to my Laravel 9 application. I’ve read in their documentation that I could run an open source server on my own instead of relying on commercial solutions. With that in mind, I decided to give Beyondcode’s Laravel Websockets a try. My application runs on PHP 8.2, using Laravel 9.19 and Laravel Websockets 1.13, communicating with the sockets through the Pusher Channels HTTP PHP Library 7.2.
Laravel Websockets is meant to match the server’s settings with the client’s by using the same naming scheme on both ends and launching off the same codebase.
This is how I’ve set up my .env
file:
APP_NAME="My app"
APP_ENV=local
APP_KEY=<redacted>
APP_DEBUG=true
BROADCAST_DRIVER=pusher
PUSHER_APP_ID="${APP_NAME}"
PUSHER_APP_KEY="${APP_KEY}"
PUSHER_APP_SECRET="${APP_KEY}${APP_NAME}"
PUSHER_HOST=ws-server
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1
My docker-compose.yml
file contains the following content:
version: "3.9"
services:
queue:
build: .
environment:
- ROLE=queue
volumes:
- .:/var/www
ws-server:
build: .
environment:
- ROLE=ws-server
volumes:
- .:/var/www
ports:
- 6001:6001
The ws-server
service has an entrypoint script which runs the following command on an infinite loop: php artisan websockets:serve --host 0.0.0.0 --port 6001
Within config/websockets.php
I’ve left everything as it comes out of the box, just so you can rest assured, this is how my apps
array looks like:
'apps' => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'path' => env('PUSHER_APP_PATH'),
'capacity' => null,
'enable_client_messages' => false,
'enable_statistics' => true,
],
]
The queue
service hosts a class called TerminalUpdated
, which looks like this:
<?php
namespace AppEvents;
use AppModelsUser;
use IlluminateBroadcastingInteractsWithSockets;
use IlluminateBroadcastingPrivateChannel;
use IlluminateContractsBroadcastingShouldBroadcast;
use IlluminateFoundationEventsDispatchable;
use IlluminateQueueSerializesModels;
use IlluminateSupportFacadesLog;
class TerminalUpdated implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public string $id;
public string $newLine;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(string $id, string $newLine)
{
$this->id = $id;
$this->newLine = $newLine;
}
/**
* Get the channels the event should broadcast on.
*
* @return IlluminateBroadcastingChannel|array
*/
public function broadcastOn()
{
return new PrivateChannel('console.' . $this->id);
}
}
Another script running within the service mentioned above executes the following sentence:
<?php
$id = '123';
$line = 'This is a line of text.';
TerminalUpdated::dispatch(
$this->id, // id
$line // newLine
);
?>
Everything looks more or less okay to me, yet I’m getting the following exception:
[2023-01-19 01:05:09] local.ERROR: Pusher error: {"error":"Invalid auth signature provided."}. {"exception":"[object] (Illuminate\Broadcasting\BroadcastException(code: 0): Pusher error: {"error":"Invalid auth signature provided."}. at /var/www/vendor/laravel/framework/src/Illuminate/Broadcasting/Broadcasters/PusherBroadcaster.php:164)
"}
I don’t seem to be able to figure out where is it even trying to generate the signature mentioned in the exception shown above.
I’ve already tried the following possible fixes:
- Restart the server
- Reset the framework’s caches and temporary files by calling
php artisan optimize:clear
2
Answers
The problem is that
PUSHER_APP_ID
can't contain spaces. Using a string without spaces instead fixes the issue. It looks like the library just can't translate the spaces to the expected URL encoding.This is how I configured the WebSocket:
In the websocket.php file :
In broadcasting.php I have:
I hope it helps you out.