I'm using Laravel Echo Server with Socket.io. Also I want to use Laravel Notifications for the Real Time Notifications.
Below is my bootstrap.js
import Echo from 'laravel-echo'
window.io = require('socket.io-client');
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':7878'
});
Below is my routes/channels.php
Broadcast::channel('App.Domain.User.User.{id}', function ($user, $id) {
return true;
});
And following is the code in my blade file:
<script>
Echo.private('App.Domain.User.User.' + '{{ auth()->user()->id }}')
.notification((notification) => {
console.log('yes');
console.log(notification.type);
$.notify('success', {type: 'success'});
});
</script>
But I'm getting the following error:
What could be the reason?
Thanks to all in advance.
Related
I am quite new to this laravel event so I am quite unable to get it done correctly.
I am trying to fire an event to notify the user when the job is completed. So, I am triggering an event at the end of the job as
event(new AmenityUploaded($this->data['property_id']));
My event looks like:
namespace App\Events;
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 AmenityUploaded implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $property_id;
public function __construct($property_id)
{
$this->property_id = $property_id;
}
public function broadcastOn()
{
return new PrivateChannel('channel.amenity.'.$this->property_id);
}
public function broadcastAs()
{
return 'amenity-uploaded';
}
}
And in routes/channel.php
Broadcast::channel('channel.amenity.{propertyId}', function ($user, $propertyId) {
// return $user->id === \App\Models\Property::find($propertyId)->updated_by;
return true;
}
And in view, I am using javascript as:
view
<script>
Pusher.logToConsole = true;
var pusher = new Pusher('xxxxxxxxxxxxxxxxxxxxx', {
cluster: 'us3',
forceTLS: true
});
$id = '<?php echo $r->id; ?>';
var channel = pusher.subscribe(`channel.amenity.${$id}`);
channel.bind('amenity-uploaded', function(data) {
alert(JSON.stringify(data));
});
</script>
And my .env looks like:
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=xxxxx
PUSHER_APP_KEY=xxxxxxxxxxxxxxxxxxxx
PUSHER_APP_SECRET=xxxxxxxxxxxxxxxxxxxx
PUSHER_APP_CLUSTER=us3
So, whenever I run the queue with php artisan queue:work --tries=3. In the end, I could see that App\Events\AmenityUploaded being fired. However, I could not see any alert on the front end.
However, If I try to push notifications from the pusher dashboard, it alerts successfully on the app successfully. While pushing from pusher debug console, I use the channel as channel.amenity.1 and event as amenity-uploaded
##Update
I have added a block in event as broadcastWith:
public function broadcastWith()
{
// This must always be an array. Since it will be parsed with json_encode()
return [
'name' => 'Saroj',
'message' => 'Message',
];
}
And, this is successfully showing in pusher dashboard. However, not alerting in the frontend yet.
update 2
Tried with echo: Added following code in bootstrap.js
import Echo from 'laravel-echo'
import Pusher from "pusher-js"
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'xxxxxxxxxxxxxxxxxxxx',
cluster: 'us3',
encrypted: true
});
And in view:
<script>
$id = '<?php echo $r->id; ?>';
Echo.channel(`channel.amenity.${$id}`)
.listen('.amenity-uploaded', (data) => {
alert(JSON.stringify(data));
});
</script>
Still the same, if fired from the pusher dashboard, an alert will be shown in frontend. After finishing jobs, the event can be seen at the pusher dashboard, however not on the frontend.
I think the issue is that you use only Pusher at frontend without laravel-echo which should be required to work with private channels. Pusher itself doesn't know that it must authorise, laravel-echo does that out of the box.
This is how I init Pusher and Echo:
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: fromPHP.PUSHER_APP_KEY,
cluster: fromPHP.PUSHER_CLUSTER,
encrypted: true
});
and this is how I listen for private events:
Echo.private(channel).listen('.amenity-uploaded', data => alert(JSON.stringify(data)));
Notice the leading . before amenity-uploaded. That's required when you customise broadcastAs (https://laravel.com/docs/5.8/broadcasting#broadcast-name)
I have been trying tog et private channels working with Laravel, and laravel-websockets
I got past a few hurdles, but the remaining one is on trying to auth:
preg_match(): Compilation failed: unrecognized character after (?< at offset 13
That error seems to be related to:
…/vendor/laravel/framework/src/Illuminate/Broadcasting/Broadcasters/Broadcaster.php150
I guess the relavant pieces of code would be the echo config and listen.
bootstrap.js
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
encrypted: false,
wsHost: window.location.hostname,
wsPort: 6001,
disableStats: true,
});
admin.blade.php
Echo.private('messages.{{Auth::id()}}')
.listen('NewMessageNotification', (e) => {
console.log(e.message.message);
});
Just in case, channels.php
Broadcast::channel('messages.{$toUserId}', function ($user, $toUserId) {
// return true;
return $user->id == $toUserId;
});
If I remove the private, everything works.
Broadcast::channel('messages.{$toUserId}', function ($user, $toUserId) {
// return true;
return $user->id == $toUserId;
});
The problem was the $ in the channel...
This is the correct way
Broadcast::channel('messages.{toUserId}', function ($user, $toUserId) {
// return true;
return $user->id == $toUserId;
});
In my ChatEvent i called function
public function broadcastOn()
{
return new Channel('chat');
}
And in app.js i have Echo.
Echo.channel('chat')
.listen('ChatEvent', (e) => {
this.chat.message.push(e.message);
console.log(e);
})
It works pretty well. But, when i change Channel to PrivateChannel in function broadcastOn() and in app.js I change
Echo.private('chat')
.listen('ChatEvent', (e) => {
this.chat.message.push(e.message);
console.log(e);
})
I have error POST broadcasting/auth 403 (Forbidden) ## And
Can I use Channel instead of PrivateChannel?
Like mentioned in document you have to define the authorization rule for this private channel
https://laravel.com/docs/5.5/broadcasting#authorizing-channels
edit your routes/channels.php file
Broadcast::channel('chat', function ($user) {
return true; //for public access
// or
return $user->can('chat'); //using gate
});
else use the channel for public access
When you use Private or PresenceChannel, Fix Error 403 /broadcasting/auth with Laravel version > 5.3 & Pusher, you need change your code in resources/assets/js/bootstrap.js with
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your key',
cluster: 'your cluster',
encrypted: true,
auth: {
headers: {
Authorization: 'Bearer ' + YourTokenLogin
},
},
});
And in app/Providers/BroadcastServiceProvider.php change by
Broadcast::routes()
with
Broadcast::routes(['middleware' => ['auth:api']]);
or
Broadcast::routes(['middleware' => ['jwt.auth']]); //if you use JWT
it worked for me, and hope it help you.
Try this
in Chat event add
public function broadcastAs()
{
return 'new.chat';
}
in your javascript file
Echo.channel('chat')
.listen('.new.chat', (e) => {
console.log(e);
})
if use api
window.Echo.connector.options.auth.headers['Authorization'] = `Bearer ${user.api_token}`;
if use session auth without top code
I am trying to make my app connecting to pusher on a private channel.
But I am getting the following error in console:
POST http://localhost:8000/broadcasting/auth 403 (Forbidden)
app.js
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('payment', require('./components/Payment.vue'));
Vue.component('form-ajax', require('./components/FormAjax.vue'));
Vue.component(
'passport-clients',
require('./components/passport/Clients.vue')
);
Vue.component(
'passport-authorized-clients',
require('./components/passport/AuthorizedClients.vue')
);
Vue.component(
'passport-personal-access-tokens',
require('./components/passport/PersonalAccessTokens.vue')
);
const app = new Vue({
el: '#app'
});
Echo.private(`articles.admin`)
.listen('ArticleEvent', function(e) {
console.log(e);
});
Error
What maybe the cause of the error and how to resolve it.
Error 403 /broadcasting/auth with Laravel version > 5.3 & Pusher, you need change your code in resources/assets/js/bootstrap.js with
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your key',
cluster: 'your cluster',
encrypted: true,
auth: {
headers: {
Authorization: 'Bearer ' + YourTokenLogin
},
},
});
And in app/Providers/BroadcastServiceProvider.php change by
Broadcast::routes()
with
Broadcast::routes(['middleware' => ['auth:api']]);
or
Broadcast::routes(['middleware' => ['jwt.auth']]); //if you use JWT
it worked for me, and hope it help you.
Have you tried to customise your authEndpoint.
this thing works on my end.
bootsrap.js
window.Echo = new Echo({
broadcaster: 'pusher',
// ...
authEndpoint: '/custom/endpoint/auth'
});
In my case I have used a custom auth guard which is causing the problem.
I have added the middleware to pass my custom auth guard and this solves the problem.
public function boot()
{
Broadcast::routes(['middleware' => 'auth:admin']);
require base_path('routes/channels.php');
}
This link explains more what's going on.
I added below code to routes/web.php and it worked.
Route::post('/broadcasting/auth', function () {
return Auth::user();
});
I Have faced same problem and this trick save my life.
go to api.php
Broadcast::routes(['predix' => 'api', 'middleware' => ['auth:api']]);
I have a private channel. And i can use it only if i authenticated on site. But in case of laravel passport i have no idea how it should be work. By default all what i need contains in cookies.
What i have:
Broadcast::routes();
Broadcast::channel('App.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
Broadcast::routes(['middleware' => ['api']]); have no effect.
How do I authenticate users through laravel passport, for that would be connected to a private channel websocket?
I been through this, and my solution was using Laravel Echo & Laravel Echo Server for SocketIo.
Retrieve the user access token, then store it in cookie or application storage, and inject it while you instantiating or re-instantiating Laravel Echo, like the following:
let Echo = require('laravel-echo')
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001'
auth: {
headers: {
Authorization: 'Bearer ' + AUTH_API_TOKEN,
},
},
});
References:
https://laravel.com/docs/5.3/broadcasting#driver-prerequisites
https://github.com/tlaverdure/laravel-echo-server
Unfortunately at the current moment the echo does not support authorization with the help of laravel passport, it is necessary to write your own sokket.io server.