Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save 1mursaleen/2f2265976d59267f3bfccb339b27be44 to your computer and use it in GitHub Desktop.
Save 1mursaleen/2f2265976d59267f3bfccb339b27be44 to your computer and use it in GitHub Desktop.
Common Problems faced while setting up private channels with laravel-echo & laravel-echo-server.
I'll start with the basics and proceed to addressing the common problems faced while setting up private channels with laravel-echo & laravel-echo-server.
I'll try to cover eveything and try to use appropriate highlighting to single out each common problem. I use '---' to separate each section or common problem.
NPM Install
npm install dotenv --save
npm install laravel-echo --save
npm install laravel-echo-server --save
npm install laravel-echo-server --save -g
note that I've installed 'laravel-echo-server' globally and locally in the project.
Global installation will allow us to use cli commands for this package, like 'laravel-echo-server init'
Local installation because of this good practice: https://medium.com/@titasgailius/running-laravel-echo-server-the-right-way-32f52bb5b1c8
---
In config/app.php
Comment out the line below
App\Providers\BroadcastServiceProvider::class,
---
In .env, you must set these variables:
APP_URL=http://your_domain.com
// common mistake: be carefull while setting the scheme 'http' or 'https' in both local and production environments.
APP_NAME=YourAppName
// I'd suggest you use a clean name without underscores, hyphens, periods or any symbols.
JWT_SECRET=random_string
JWT_TTL=1440
// set these only if you are using this package for jwt authentication https://github.com/tymondesigns/jwt-auth
CACHE_DRIVER=redis // optional but I'd suggest redis
SESSION_DRIVER=redis // optional but I'd suggest redis
QUEUE_CONNECTION=redis // this refers to the config/queue.php file
BROADCAST_DRIVER=redis
Important Note:
your Redis installation has 0 to 16 DBs
If you plan to use redis as CACHE_DRIVER, SESSION_DRIVER and BROADCAST_DRIVER -- which I'd certainly suggest -- you must use different DB for each driver.
It is widely reported by many laravel developers that redis pub/sub for BROADCAST_DRIVER is affected if a single redis db is used.
To use different DBs make the below entries in .env, each of these we'll set in config/database.php as redis connections.
REDIS_DB=0
REDIS_CACHE_DB=1
REDIS_BROADCAST_DB=2
---
In config/database.php, at the bottom there is 'Redis Databases' section in which redis's 'default' & 'cache' connections are defined like this
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
'cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
// add 'broadcast' db connection after 'cache' like this:
'broadcast' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_BROADCAST_DB', 2),
],
---
In app\Providers\BroadcastServiceProvider.php, make sure the boot function has Broadcast::routes() and requires 'routes/channels.php'
public function boot()
{
Broadcast::routes(); // by default these routes use middleware 'auth:web'
// Broadcast::routes(['middleware' => ['auth:api']]); // for auth:api
// Broadcast::routes(['middleware' => ['jwt.auth']]); // for jwt package https://github.com/tymondesigns/jwt-auth
require base_path('routes/channels.php');
}
---
In config/database.php, at the bottom under redis db settings if you have: redis -> options -> prefix
Then all your channels that you brodcast on will have a prefix 'YourAppName_database_' or 'laravel_database_'
for example: YourAppName_database_mymessageschannel
'redis' => [
'client' => env('REDIS_CLIENT', 'predis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'predis'),
'prefix' => Str::slug(env('APP_NAME', 'laravel'), '_').'_database_',
// You can customize the prefix however you want, but keep in mind that while listening to the channles you'll have to use this prefix
],
...
]
---
use 'php artisan make:event EventName' to make an event that should be broadcast. The new Event will be placed in 'app\Events' directory.
I used 'php artisan make:event MessageSent'
then in app\Events\MessageSent
<?php
namespace App\Events;
use App\Message;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public function __construct(Message $message)
{
//
$this->message = $message;
//
$this->dontBroadCastToCurrentUser(); // if you don't want to broadcast to the user who generated the event.
}
public function broadcastOn()
{
return new PrivateChannel("room." . $this->message->room_id);
// Very very Important Note: because it sucked a lot of my time
// If you have a redis prefix setup in config/database.php, which I have discussed in the previous section,
// you'll have to use the prefix while listening to the channel in Laravel Echo.
// for example: if you have prefix 'YourAppName_database_', the resulting channel will be 'YourAppName_database_room.{room_id}'
}
}
---
In routes/channels.php
Broadcast::channel('room.{id}', function ($user, $id) {
return (int) $user->room_id === (int) $id;
},
['guards' => ['api']]); // you can optionally give guards as the third agument, if you are using a guard other than the 'web' guard.
// the user must be logged in to authenticate private channels, laravel will automatically place $user as the current logged in user.
// Important Note: Again, if there's a redis prefix setup, as I have discussed in the section above you must prefix it here
// Broadcast::channel('YourAppName_database_room.{id}', function ($user, $id) {
// 'YourAppName_database_' is the redis prefix.
---
Do 'npm install --save socket.io-client'
In resources\...\bootstrap.js, configure import and configure Laravel Echo for laravel-echo-server
import Echo from 'laravel-echo'
window.io = require('socket.io-client');
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001'
});
---
// make echo.js in the project directory (where .env is) and copy paste below code and save
// here we use the locally installed 'laravel-echo-server' package
// dotenv will help you get variables from .env file so you'll have a single environment file for both laravel and laravel-echo-server
// after you save the code, you can open a terminal in the project directory and run 'node echo' to start laravel-echo-server
require('dotenv').config();
const env = process.env;
require('laravel-echo-server').run({
authHost: env.APP_URL,
devMode: env.APP_DEBUG,
database: "redis",
databaseConfig: {
redis: {
host: env.REDIS_HOST,
port: env.REDIS_PORT,
family: 4,
db: env.REDIS_BROADCAST_DB // 'REDIS_BROADCAST_DB' is the separate db we have setup in the previous section for broadcast channels
}
}
// more laravel-echo-server options can be added, see it's documentation
});
---
In your vue component, where you'd like to listen to your channel
forexample: resources\js\components\ExampleComponent.vue
mounted () {
var that = this
// if you are using jwt auth, you must set the following headers of window.Echo options to get authenticated for private channels and you must have a mechanism to get the jwt token
// window.Echo.connector.options.auth.headers['Authorization']
// window.Echo.options.auth
// if you are not using jwt, skip the two lines below
window.Echo.connector.options.auth.headers['Authorization'] = 'Bearer ' + jwt_token
window.Echo.options.auth = {
headers: {
Authorization: 'Bearer ' + jwt_token,
},
},
window.Echo.private(`room.${that.room.id}`) // *
.listen('MessageSent', function (e)
{
// doStuff
})
// *
// Important Note: Again, if there's a redis prefix setup, as I have discussed in the previous sections you must prefix it here
// window.Echo.private(`YourAppName_database_room.${that.room.id}`)
// the channel name becomes YourAppName_database_room.{room_id}
// 'YourAppName_database_' is the redis prefix.
}
@interludic
Copy link

Sweet mother of god

@flowser

This comment was marked as abuse.

@litvinenkow
Copy link

where is auth routes configured?

@yatutmaster
Copy link

yatutmaster commented Oct 21, 2020

Thanks, kind man!

@M-Abdullahi
Copy link

Setting up websockets with vue and laravel echo is a pain in the ass. Used 8hrs+ and still not getting it to run

@swanback
Copy link

swanback commented Jan 7, 2021

This is a fantastic help. Had I found the key that as of Jan 2021 at least, you must use socket.io-client version 2.3.0, not version 3.0, it would have saved me many (more) hours of head-banging.

@Mozakar
Copy link

Mozakar commented Apr 13, 2021

you must use socket.io-client version 2.3.0, not version 3.0, it would have saved me many (more) hours of head-banging.

Thanks, I wasted two weeks because of the version

@rahul1961
Copy link

Setting up websockets with vue and laravel echo is a pain in the ass. Used 8hrs+ and still not getting it to run

Just if you are wondering, there is this prefix on laravel-echo for client side, called, private, so if you have a laravel private channel xyz, for laravel echo to work, you need to rename it to private-xyz then only It will work.

@Geovanek
Copy link

Geovanek commented Oct 14, 2021

I have this error and I don't know what can solve it.

laravel-echo-server_1  | [12:20:31 AM] - Sending auth request to: localhost/broadcasting/auth
laravel-echo-server_1  |
laravel-echo-server_1  | [12:20:31 AM] - Error authenticating wcoGigP-jG_jjDARAAAL for private-athletes.1
laravel-echo-server_1  | Error: Invalid URI "localhost/broadcasting/auth"
laravel-echo-server_1  |     at Request.init (/usr/src/app/node_modules/request/request.js:273:31)
laravel-echo-server_1  |     at new Request (/usr/src/app/node_modules/request/request.js:127:8)
laravel-echo-server_1  |     at request (/usr/src/app/node_modules/request/index.js:53:10)
laravel-echo-server_1  |     at Function.post (/usr/src/app/node_modules/request/index.js:61:12)
laravel-echo-server_1  |     at /usr/src/app/node_modules/laravel-echo-server/dist/channels/private-channel.js:57:27
laravel-echo-server_1  |     at new Promise (<anonymous>)
laravel-echo-server_1  |     at PrivateChannel.serverRequest (/usr/src/app/node_modules/laravel-echo-server/dist/channels/private-channel.js:54:16)
laravel-echo-server_1  |     at PrivateChannel.authenticate (/usr/src/app/node_modules/laravel-echo-server/dist/channels/private-channel.js:21:21)
laravel-echo-server_1  |     at Channel.joinPrivate (/usr/src/app/node_modules/laravel-echo-server/dist/channels/channel.js:68:22)
laravel-echo-server_1  |     at Channel.join (/usr/src/app/node_modules/laravel-echo-server/dist/channels/channel.js:21:22)
laravel-echo-server_1  | Error sending authentication request.````

@1mursaleen
Copy link
Author

I have this error and I don't know what can solve it.

laravel-echo-server_1  | [12:20:31 AM] - Sending auth request to: localhost/broadcasting/auth
laravel-echo-server_1  |
laravel-echo-server_1  | [12:20:31 AM] - Error authenticating wcoGigP-jG_jjDARAAAL for private-athletes.1
laravel-echo-server_1  | Error: Invalid URI "localhost/broadcasting/auth"
laravel-echo-server_1  |     at Request.init (/usr/src/app/node_modules/request/request.js:273:31)
laravel-echo-server_1  |     at new Request (/usr/src/app/node_modules/request/request.js:127:8)
laravel-echo-server_1  |     at request (/usr/src/app/node_modules/request/index.js:53:10)
laravel-echo-server_1  |     at Function.post (/usr/src/app/node_modules/request/index.js:61:12)
laravel-echo-server_1  |     at /usr/src/app/node_modules/laravel-echo-server/dist/channels/private-channel.js:57:27
laravel-echo-server_1  |     at new Promise (<anonymous>)
laravel-echo-server_1  |     at PrivateChannel.serverRequest (/usr/src/app/node_modules/laravel-echo-server/dist/channels/private-channel.js:54:16)
laravel-echo-server_1  |     at PrivateChannel.authenticate (/usr/src/app/node_modules/laravel-echo-server/dist/channels/private-channel.js:21:21)
laravel-echo-server_1  |     at Channel.joinPrivate (/usr/src/app/node_modules/laravel-echo-server/dist/channels/channel.js:68:22)
laravel-echo-server_1  |     at Channel.join (/usr/src/app/node_modules/laravel-echo-server/dist/channels/channel.js:21:22)
laravel-echo-server_1  | Error sending authentication request.````

Everyone! I suggest every developer should use LARAGON and ditch xampp wampp etc.
You'll save a lot of time on setting up & resolving environment issues, like this localhost issue.
You'll get http://{project}.test urls automatically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment