-
-
Save 1mursaleen/2f2265976d59267f3bfccb339b27be44 to your computer and use it in GitHub Desktop.
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. | |
If you are getting these errors while setup; 401, 403, 419 etc, as I did in my experience. | |
this gist will help you fix these errors. | |
Although this gist addresses common problems of laravel-echo-server setup, some problems are similar with Pusher setup. | |
So it might also be useful if you're having problems with setting up Pusher with Echo. | |
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 | |
--- | |
first and foremost, make sure you have csrf meta tag in the html <head>. Otherwise you'll get 419 error while listening to channels | |
<meta content="{{ csrf_token() }}" name="csrf-token"> | |
--- | |
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. | |
// this mistake can cause 403, 404 error or an error without a status | |
APP_NAME=YourAppName | |
// I'd suggest you use a clean name without underscores, hyphens, periods or any symbols. | |
// errors: 401 403 | |
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 | |
// error: events are published to channels but echo-server won't listen | |
--- | |
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 | |
// error: events are published to channels but echo-server won't listen | |
], | |
... | |
] | |
--- | |
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}' | |
// error: 401, 403 | |
} | |
} | |
--- | |
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. | |
// error: 401, 403 | |
--- | |
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. | |
// error: 401, 403 | |
} | |
Thanks, kind man!
Setting up websockets with vue and laravel echo is a pain in the ass. Used 8hrs+ and still not getting it to run
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.
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
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.
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.````
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.
where is auth routes configured?