I can't manage to get echo and pusher working when using private channels, googled for two days and found nada.
What seems to be happening is some sort of problem with the authentication (I'm using Laravel basic Auth) cause I can subscribe to public channels
routes/channels.php
Broadcast::channel('private-ci-received-{userId}', function ($user, $userId) {
return (int) $user->id === (int) $userId;
});
Broadcast::channel('private-ci-received-{toUserId}', function ($currentUser, $toUserId) {
return true;
});
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,
logToConsole: true,
encrypted: true,
});
default.blade.php(main layout)
Pusher.logToConsole = true;
Echo.logToConsole = true;
Echo.private('ci-received-{{ Auth::user()->id}}')
.listen('.CIReceived', (e) => {
console.log(e);
});
What get printed on the console is :
Pusher : No callbacks on private-ci-received-1 for pusher:subscription_error
It's a pretty generic error, then for debug purposes I tried to bind the error using Pusher (not laravel echo)
var pusher = new Pusher('MYSECRETAPPKEYHERE', {
cluster: 'us2',
forceTLS: true
});
var channel = pusher.subscribe('private-ci-received-1');
channel.bind('pusher:subscription_error', function(data) {
console.log(data);
});
console.log(data) output
JSON returned from webapp was invalid, yet status code was 200
The default authEndPoint is /broadcasting/auth IIRC I think it expects to return a JSON but instead it returns the HTML CODE from my page.
Those routes are created by the framework itself and from what I've read Laravel echo and Laravel Auth should work great together without much fiddling.
My .env file is correct i'm using pusher as broadcast driver and BroadcastServiceProvider is properly uncommented.
Can anyone shed a light in the matter? Thanks
This worked for me
Default value of .env is
BROADCAST_DRIVER=log
Pls change it to
BROADCAST_DRIVER=pusher
I was also getting ["No callbacks on private-user.1 for pusher:subscription_error"]
After making the above changes, it works fine for me
Set APP_DEBUG=true in your .env file and check the HTTP response of your auth route in the network section of your browser's developer tools. If authentication is successful, your laravel app should respond with JSON like this:
{"auth": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
If there's an error it will show you in the response since you set debug mode to true.
You do not need to add private- onto your channel in broadcasting.php this is done automagically
Try this
Broadcast::channel('ci-received-{userId}', function ($user, $userId) {
return (int) $user->id === (int) $userId;
});
Related
I'm trying to keep only one connection active per user who open multiple tabs on my application that uses Pusher with Laravel Echo, I was able to get it working on a test project by following the article and the example project below.
https://blog.pusher.com/reduce-websocket-connections-with-shared-workers/
https://github.com/pusher-community/pusher-with-shared-workers
But I'm having a hard time trying to adapt it to work with my Laravel project, how should I do that?
Here is the configuration I have added to my bootstrap.js file
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
});
$.getJSON( "/heartbeat", function( json ) {
window.Echo.channel('user.' + json.user_id).listen('NotifyUser', e => {
displayModal(e.msg);
console.log('User with an id of ' + e.id + ' has been notified.');
console.log(e);
// Relay the message on to each client
clients.forEach(function(client){
client.postMessage(data);
});
});
});
self.addEventListener("connect", function(evt){
// Add the port to the list of connected clients
var port = evt.ports[0];
clients.push(port);
// Start the worker.
port.start();
});
It's working but not the way I want, it's creating a new connection for each opened tab.
As specified in the link you provided yourself: https://blog.pusher.com/reduce-websocket-connections-with-shared-workers/ , you need to import a specific version of pusher to use worker: pusher.worker.js.
So, go here: https://github.com/pusher/pusher-js/tree/master/dist/worker
and download the pusher.worker.min.js . Put it in the same directory as your boostrap.js and require it. Instead of:
window.Pusher = require('pusher-js');
use
importScripts("pusher.worker.min.js");
I'm using pusher in my project.in console debug show the event when I want to connect to the channel in the dashboard show the Disconnection status and I don't get the event on javascript App.
js Code:
Echo.private(`order.${orderId}`)
.listen('NewChat', (e) => {
console.log(e.message);
}
);
Broadcast config:
PUSHER_APP_ID=625***
PUSHER_APP_KEY=bcd15f3d3c6*******
PUSHER_APP_SECRET=c8e7e09d21********
PUSHER_APP_CLUSTER=ap2
bootstrap.js:
import Echo from 'laravel-echo'
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'bcd15f3d3***********',
cluster: 'ap2',
encrypted: false
});
event:
public function broadcastOn()
{
return new PrivateChannel('order.'.$this->order_id);
}
channel:
Broadcast::channel('order.{orderId}', function () {
return true;
});
console debug status
I have no real experience iwth Laravel in combination with pusher, but i see the following:
Broadcast::channel('order.{orderId}',
{orderId} wont be translated to an variable value. You need {$orderId}. Also, doing this in a single quoted string wont work because it will just print {$orderId}, so you need double quotes.
Try the following:
Broadcast::channel("order.{$orderId}",
Maybe this will solve your problem, maybe not.
If not, are you sure private(order.${orderId}) is using the right Id?
Check if return new PrivateChannel('order.'.$this->order_id); is using the right $this->order_id.
Trying to subscribe to a private channel with Pusher. But every time it tries to subscribe I get the error below. Which makes no sense since it's clearly returning the auth info.
Pusher : Error : {"type":"WebSocketError","error":{"type":"PusherError","data":{"code":null,"message":"Auth info required to subscribe to private-sadfsadf"}}}
Normally it's returning the auth json (below) with status 200.
"{\"auth\":\"0b1ce844906bd4d82cb4:21571e5667bf99f17bbf67ae0411594560748fde30b9edeca653653158f8a1f5\"}"
Pusher PHP (shortened)
$pusher = new Pusher($app_key, $app_secret, $app_id);
$auth = $pusher->socket_auth($postvars['channel_name'], $postvars['socked_id']);
if ($auth)
return $response->withJSON($auth);
else
return $response->withStatus(403);
Pusher JS
var pusher = new Pusher('0b1ce844906bd4d82cb4', {
cluster: 'us2',
encrypted: true,
authEndpoint: '{{site.uri.public}}/chat/auth/{{game.id}}',
authTransport: 'ajax',
auth: {
params: {
'csrf_name': '{{site.csrf.name}}',
'csrf_value': '{{site.csrf.value}}'
},
headers: {
'{{site.csrf.name}}': '{{site.csrf.value}}'
}
}
});
I had this error and it was caused by having the BROADCAST_DRIVER set to redis instead of pusher.
it was because my endpoint /pusher/auth returned the signature in JSON format.
So, I just changed this:
return $response
To this:
return json_decode($response)
NB: PUSHER signature use hash_hmac to generate hash:
you can compare you entryPoint return with
$sig = hash_hmac('sha256',$socket, $channelNam);
var_dump($sig);
we are using Pusher as our notification system and it is causing problem sometimes.
The issue is sometimes the connection closes automatically and the following error is printed on the console (actually this is an older error I used to get on console until some weeks ago):
Pusher : Error :
{"type":"WebSocketError","error":{"type":"PusherError","data":{"code":1006}}}
And recently I see this one:
Pusher : Error : {"type":"WebSocketError","error":{"type":"PusherError","data":{"code":4200,"message":"Please reconnect immediately"}}}
Here is the client (JS) code:
function initPusher(user) {
if (pusher) {
return;
} else {
Pusher.logToConsole = false;
pusher = new Pusher('pusher key', {
cluster: 'eu',
encrypted: true
});
try {
var channel = pusher.subscribe(user.user_channel);
channel.bind('app_event', function(data) {
if (data['event_type'] === 'reply-message') {
$rootScope.$broadcast('REPLY_RECEIVED', data);
} else if (data['event_type'] === 'new-message') {
$rootScope.$broadcast('MESSAGE_RECEIVED', data);
}
});
} catch(err) {
$state.go('logout');
}
}
}
This function is called on login and every page refresh.
Although I guess this is a client side issue I add the relevant PHP code where the API is instantiated in index.php:
require_once __DIR__.'/../vendor/pusher/pusher-php-server/lib/Pusher.php';
$options = array(
'cluster' => 'eu',
'encrypted' => true
);
$pusher = new Pusher(
'pusher key',
'secret',
'app id,
$options
);
Further Details
Backend framework in use is Silex and the frontend one AngularJS.
We are using the EU cluster of Pusher and it works fine while the connection is still open.
I have already seen this link but couldn't find an answer to my problem there.
i work on laravel 5.2 and i added vinkla/laravel-pusher to do real time chat app on my site but i faced this issue:
"JSON returned from webapp was invalid, yet status code was 200."
this my controller:
public function authMessageChat(Request $req)
{
$channelName = e($req->input('channel_name'));
$socketId = e($req->input('socket_id'));
$auth = $this->pusher->presence_auth($channelName, $socketId, auth()->user()->id);
return response($auth);
}
this is my script:
var pusher = new Pusher('{{env("PUSHER_KEY")}}', {
authEndpoint: '../auth',
auth: {
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
params: {
id: currentUser.id
}
}
});
var channel = pusher.subscribe('{{$chatChannel}}');
channel.bind('pusher:subscription_error', function(PusherError){
console.log('PusherError' + PusherError);
});
channel.bind('new-message', function(data) {
console.log(data.sender);
)};
Pusher error:
#chrismou Thank you for your answer..
your answer is right and we can implement the solution in another way..
just go to your .env file and make:
APP_DEBUG=false
instead of
APP_DEBUG=true
Thank you
It looks like your app is returning the debugbar html as part of the json response.
Assuming it's the barryvdh/laravel-debugbar you're using, according to the documentation you can switch off the debug bar at runtime:
Config::set('laravel-debugbar::config.enabled', false);
I assume you'll need to add that prior to the response being sent, in the controller method/route you're using for the authentication endpoint (ie, the one you're calling the socket_auth method from)