Hello I'm trying to make chat system for my app but I'm having problem making pusher and echo work. When I open my Chat between 2 people it does not update in real time and I have to refresh the page in order to get the updated stuff like messages and such. In console I'm getting these 2 errors
POST http://localhost/broadcasting/auth 403 (Forbidden)
POST http://localhost/broadcasting/auth 500 (Internal Server Error)
bootstrap.js
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
encrypted: true,
});
ChatBroadcast.php
class ChatBroadcast implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $ticket;
/**
* Create a new event instance.
*
* #param $ticket
*/
public function __construct(Ticket $ticket)
{
$this->ticket = $ticket;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('tickets_channel.' . $this->ticket->id);
}
public function broadcastWith(){
$messages = Message::all()->where('ticket_id','=',$this->ticket->id)->sortBy('created_at');
return [
'ticket' => $this->ticket,
'messages' => $messages
];
}
}
channels.php
use App\Ticket;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('App.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
Broadcast::channel('tickets_channel.{ticketID}', function ($user, $ticketID) {
Auth::check();
$ticket = Ticket::all()->where('id', '=', $ticketID)->first();
return $ticketID == $ticket->id;
});
VueComponent
mounted() {
Echo.private('tickets_channel.${ticketID}')
.listen('ChatBroadcast', (e) => {
console.log(e);
this.messagesMutable = e.messages;
this.state = e.ticket.isOpened;
});
},
This is my log for 500 error
[2020-09-08 09:25:24] local.ERROR: Invalid channel name private-tickets_channel.${ticketID} {"userId":11,"exception":"[object] (Pusher\\PusherException(code: 0): Invalid channel name private-tickets_channel.${ticketID} at /Users/miroslavjesensky/Documents/Blog/vendor/pusher/pusher-php-server/src/Pusher.php:282)
-EDIT-
I have managed to fix the 500 error by changing VueComponent code to this
mounted() {
let id = this.ticket.id;
Echo.private('tickets_channel' + id)
.listen('ChatBroadcast', (e) => {
this.messagesMutable = e.messages;
this.state = e.ticket.isOpened;
});
},
Turns out the problem was with another VueComponent I am using with the first one. After fixing the listening part of echo there aswell all works as it should
Related
I'm using laravel 8, and I'm having a hard time getting the data from the event using pusher. I'm want to broadcast the event, i want to receive the data when the data is successfully inserted in the database. hope someone can help me with this. here are my codes
config/app.php
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class
Events\Chat.php
class Chat implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* #return void
*/
public $data;
public function __construct($data)
{
$this->data = $data;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('chat');
}
public function broadcastAs()
{
return 'get-chat';
}
}
chat.blade.php
var pusher = new Pusher('dec355f1ff67f51f5784', {
cluster: 'ap1',
forceTLS: true
});
Pusher.logToConsole = true;
$('.chat-send').click(function(){
var msg = $('.chat-msg').val();
$.ajax({
url: add_url,
type: 'POST',
data: {'msg' : msg},
dataType: 'json',
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
success: function(data) {
if (data.msg == 'success') {
var channel = pusher.subscribe('chat');
channel.bind('pusher:subscription_succeeded', function(data) {
//alert('successfully subscribed!');
console.log(data);
});
channel.bind('get-chat', function(data) {
//console.log(JSON.stringify(data));
alert(data);
});
}
},
error : function(request, status, error) {
//swal("Oops!", "Seems like there is an error. Please try again", "error");
}
});
});
MessageController
public function create(Request $request, Messages $messages)
{
$request->merge([
'teacher_id' => 2,
'student_id' => 1,
'message' => 'test msg'
]);
$data = $messages::create($request->all());
if ($data->exists) {
$msg = 'success';
$cars = ['hey', 'yow'];
broadcast(new Chat($cars));
}
return json_encode(['msg'=>$msg]);
}
This is what I get in the pusher.log
Pusher : : ["Event sent",{"event":"pusher:subscribe","data":{"auth":"","channel":"chat"}}]
Pusher : : ["Event recd",{"event":"pusher_internal:subscription_succeeded","channel":"chat","data":{}}]
I am getting a 403 on broadcasting/auth route.
I am using Laravel websockets package for web sockets and I have the below setup
- Backend Laravel server ( on port 8000 )
- Laravel Websockets Server ( laravel is running on 8001 and websocket server on 6001 )
- Standalone Ionic React app ( on port 8100)
Now everything works when I am trying Public Channel but when I try Private Channel it fails.
in the above screenshot of Laravel sockets dashboard I can see connection made as this is the same socketId which went with the request.
I am using Laravel Sanctum for Authentication.
PFB :- my client side code
const headers = {
'Content-Type': 'application/json',
Authorization: window.localStorage.getItem('token')
? `Bearer ${window.localStorage.getItem('token')}`
: '',
'Access-Control-Allow-Credentials': true,
};
const options = {
broadcaster: 'pusher',
key: 'abcsock',
authEndpoint: 'http://localhost:8001/api/broadcasting/auth',
authorizer: (channel, options) => {
return {
authorize: (socketId, callback) => {
axios
.post(
'http://localhost:8001/api/broadcasting/auth',
{
socket_id: socketId,
channel_name: channel.name,
},
{ headers, withCredentials: true }
)
.then((response) => {
callback(false, response.data);
})
.catch((error) => {
callback(true, error);
});
},
};
},
wsHost: '127.0.0.1',
wsPort: 6001,
encrypted: true,
disableStats: true,
enabledTransports: ['ws', 'wss'],
forceTLS: false,
};
Code from Laravel Websockets Server
api.php file
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Broadcast;
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
Broadcast::routes(['middleware' => ['auth:sanctum']]);
BroadcastServiceProvider.php
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
Broadcast::routes(['middleware' => ['auth:sanctum']]);
require base_path('routes/channels.php');
}
}
NewNotification.php
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\BroadcastMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Broadcasting\PrivateChannel;
use App\AppNotification;
use App\User;
class NewNotification extends Notification
{
use Queueable;
public $notification;
public $user;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct(AppNotification $notification, User $user)
{
$this->notification = $notification;
$this->user = $user;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['database', 'broadcast'];
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
$notification = $this->notification;
return [
'id' => $notification->id,
'title' => $notification->title,
'description' => $notification->description,
'button_text' => $notification->button_text,
'is_read' => $notification->is_read,
'created_at' => $notification->created_at,
[
'notification_for' => $notification->notifiable
]
];
}
public function toBroadcast($notifiable)
{
return new BroadcastMessage($this->toArray($notifiable));
}
public function broadcastOn()
{
return new PrivateChannel('Notifications.' . $this->user->id);
}
}
channels.php
<?php
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('Notifications.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
}, ['guards' => ['sanctum']]);
I have attached whatever I felt was sufficient to explain the issue and for you to troubleshoot but if you need anything more please ask.
Any help will be appreciated
i liked this package because its wrote in php but its sortof abandon and a lot of issues that not solved.
alternative of this server is laravel-echo-server(as laravel docs recommends) very easier to use.
https://stackoverflow.com/a/61704796/7908390 more info if you can work with laravel-sockets im glad to see a new example
Have you added authentication for your channels.php? Please refer here:
https://laravel.com/docs/7.x/broadcasting#defining-authorization-routes
What does it look like?
I think you are doing everything correctly but you have not authorized your routes.
I had the similar error with Laravel & pusher.
I have fixed using decodeURIComponent and moving BroadCast::routes(['middleware' => ['auth:sanctum']]) to routes/api.php from BroadcastServiceProvider.php
Also, add withCredentials = true.
const value = `; ${document.cookie}`
const parts = value.split(`; XSRF-TOKEN=`)
const xsrfToken = parts.pop().split(';').shift()
Pusher.Runtime.createXHR = function () {
const xhr = new XMLHttpRequest()
xhr.withCredentials = true
return xhr
}
const pusher = new Pusher(`${process.env.REACT_APP_PUSHER_APP_KEY}`,
{
cluster: 'us3',
authEndpoint: `${process.env.REACT_APP_ORIG_URL}/grooming/broadcasting/auth`,
auth: {
headers: {
Accept: 'application/json, text/plain, */*',
'X-Requested-With': 'XMLHttpRequest',
'X-XSRF-TOKEN': decodeURIComponent(xsrfToken)
}
}
})
I hope this helps a bit.
Im making a chat in my app and Im using pusher. I did everything that pusher told me to do. I'm using vanilla-js in frontend. I can connect in frontend. I can receiver messages from pusher (look at channel.bind()) but my messages are not going anywhere.
P.S I did all configuration (.env, broadcasting.php)
FRONTEND
var pusher = new Pusher('xxxxxxxx', {
cluster: 'eu',
forceTLS: false
});
window.channelName = 'my-channel-' + {{ $chat->id }};
window.event = 'private-conversation';
var channel = pusher.subscribe(window.channelName);
channel.bind(window.event, function (data) {
alert(data);
});
BACKEND
public function sendMessage($request, $roomId){
event(new Event(array(
'id' => auth()->user()->id,
'full_name' => auth()->user()->fullName()
), $request->input('channel'), $request->input('event'), $request->input('message')));
}
EVENT
class Event
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user;
public $message;
public $channelName;
public $event;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($user, $channelName, $event, $message)
{
$this->user = $user;
$this->channelName = $channelName;
$this->event = $event;
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return [$this->channelName];
}
public function broadcastAs()
{
return $this->event;
}
}
In my app i using from pusher to send notification for typists.but i giving this error:
Couldn't get auth info from your webapp : 500
javascript codes of pusher placed in footer:
<script src="https://js.pusher.com/4.1/pusher.min.js"></script>
<script>
Pusher.logToConsole = true;
var pusher = new Pusher('xxxxxxxxxxxxxxxxx', {
cluster: 'ap2',
encrypted: true,
authEndpoint: "/broadcasting/auth",
auth: {
params: {
'X-CSRF-Token': $('meta[name="csrf-token"]')
.attr('content')
}
}
});
var channel = pusher.subscribe(
'private-App.Typist.' + {{$typistId}}
);
channel.bind('NewTypeOrder', function(data) {
alert('hi');
});
in channels.php
Broadcast::channel('App.Typist.{id}', function (Typist $typist, $id) {
return true;
});
and in Events/EventTypeOrder.php
class NewTypeOrder implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $typist;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Typist $typist)
{
$this->typist = $typist;
}
/**
* Get the channels the event should broadcast on.
*
* #return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('App.Typist.' . $this->typist->id);
}
}
my typists table is quite from users table and laravel authentication for typist not used because laravel authentication just used for users only.
in laravel.log
[2018-07-22 20:27:38] local.ERROR: ErrorException: Key file
"file://C:\xampp\htdocs\samane_typax_5.4\storage\oauth-public.key"
permissions are not correct, should be 600 or 660 instead of 666 in
C:\xampp\htdocs\samane_typax_5.4\vendor\league\oauth2-
server\src\CryptKey.php:57
Stack trace:
Now what can i do for this issue?
On the commandline, type: php artisan tinker
Then paste the following:
chmod(storage_path('oauth-public.key'), 0660)
This should set the right file permissions, the error should vanish/change once enter is pressed :)
i had a problem when using presence channel in Laravel Echo with pusher. when I fire an event, i get 500 error from BroadcastException without the response body which is hard for me to debug it. when i look to pusher debug console, the presence event was listened by pusher. so i assume my event has never been fired to Pusher. Here is the preview in my network tab
my controller:
public function store() {
$user = auth()->user();
$message = $user->messages()->create([
'message' => request('message')
]);
event(new MessageReceived($message, $user));
return ['status' => 'OK'];
}
the MessageReceived class
namespace App\Events;
class MessageReceived implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public $user;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Message $message, User $user)
{
$this->message = $message;
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* #return Channel|array
*/
public function broadcastOn()
{
return new PresenceChannel('chatroom');
}
}
and here is my vuejs
mounted() {
axios.get('/messages')
.then(response => {
this.messages = response.data
})
.catch(error => {
console.log(error)
})
Echo.join('chatroom')
.listen('MessageReceived', (e) => {
console.log(e) //never get into this
})
},
i can't find where the error is. i use cluster ap1 and is declared in broadcasting.php and in my bootstrap.js. anyone can help me out?
This can be caused by an error in your configuration. Here are some things to check:
In your .env file, make sure the pusher id, key, and secret are correctly set.
If you upgraded from Laravel 5.3 to Laravel 5.4, note that the .env variables PUSHER_KEY is now PUSHER_APP_KEY and PUSHER_SECRET is now PUSHER_APP_SECRET
In your config/broadcasting.php, make sure the cluster is set correctly.
If you are not in HTTPS, you may have to set the 'encrypted key to false
'options' => [
'cluster' => 'ap1', // change this to your app's cluster
'encrypted' => false,
],