Why laravel broadcast channel has default prefix? - laravel

currently i am working on a mobile application using react native, and as back end i am using Laravel.
As a channels client library at the client side i am using Pusher
This is how my channel route looks like in the back end
Broadcast::channel('conversation.{message_id}', function ($user,$id) {
return true;
});
I can broadcast successfully, but at pusher debug console i've noticed that a prefix (private-) added to the route.
Here is how i listen to event
const pusher = new Pusher('XXXX', {
cluster: 'eu',
authEndpoint: 'http:backend.test/api/broadcasting/auth',
auth: {
headers: {
Authorization: `Bearer `+token,
Accept: 'application/json',
},
},
});
const channel = pusher.subscribe('private-conversation.7');
channel.bind('App\\Events\\MessageSent', function (data) {
console.log("event")
console.log(data);
});
As you can see in my code i subscribe to "private-conversation.7", pusher debug console shows that the client is subscribed to channel successfully, but the issue is that the client didn't listen to events, when i create a custom event in pusher and set "conversation.7" as a channel name (i removed private- prefix) the event triggered with success.
Any suggestions please?

That is a convention used to separate private, public and presence channel.
When you subscribe a channel with private- prefix, it will require the auth process.
Laravel will automatically add private- prefix to channel name when broadcast.
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\PrivateChannel
*/
public function broadcastOn()
{
return new PrivateChannel('orders.'.$this->order->id);
}
Here are reference docs:
https://pusher.com/docs/channels/using_channels/private-channels

Related

How to use private channel in Laravel Pusher.js

I use Pusher.js in Laravel.
Here is a private channel:
return new PrivateChannel('user.'.$this->user->id);
With permissions:
Broadcast::channel('user.{userId}', function ($user, $userId) {
return true;
});
The PrivateChannel has channel prefix name in constructor:
parent::__construct('private-'.$name);
Therefore I use private- prefix in JS client:
var channel = pusher.subscribe('private-user.1');
channel.bind('PrivateEvent', function(data) {
console.log(data);
});
The problem is I got client error, because the private channel awaits auntification:
Pusher : : ["Error: Unable to retrieve auth string from channel-authorization endpoint - received status: 404 from /pusher/auth. Clients must be authenticated to join private or presence channels.
Why should I use auntification twice if Laravel already checks this in route channel?
You need first to authorize your request by adding the authEndpoint and add the jwt_token like this after that you could listen to the channel
var pusher = new Pusher("PUBLIC_KEY", {
cluster: 'eu',
authEndpoint: `https://domain_name.com/broadcasting/auth`,
auth: {
headers: {
"Authorization": "Bearer YOUR_JWT_TOKEN",
"Access-Control-Allow-Origin": "*"
}
}
});
var channel = pusher.subscribe('private-user.1');
channel.bind('PrivateEvent', function(data) {
console.log(data);
});

Issue Broadcasting to Socket.io Rooms of A Namespace

I'm trying to set up a server that can dynamically create many rooms for many namespaces. I'm currently just trying to broadcast to sockets of a room, when a new socket has joined that room.
So far I have been able to broadcast to a specific namespace and my event listeners on the client receives the message. However when I try to broadcast to a room, of a specific namespace, my event listener doesn't receive that message.
I've turned on the Debugger mode and see the socket.io-client:socket emitting the event with the right payload and event type. So I am not sure what I am missing since the documentation also seems fairly straightforward. Any help would be much appreciated. Below is my code.
Server
const colorNs = io.of('/color');
colorNs.on('connection', (socket) => {
const { id } = socket.handshake.query;
const { id:connId } = socket.conn;
if(id) {
socket.join(id);
socket.broadcast.to(id).emit('user:connect', { id: connId });
}
socket.on('disconnect', () => {
const { id } = socket.handshake.query;
const { id:connId } = socket.conn;
socket.broadcast.to(id).emit('user:disconnect', { id: connId });
});
});
Client
const socket = io('/color?id="123"');
socket.on('user:connect', () => console.log('data', data));
Client - Debug Trace
socket.io-parser decoded 2/color,["user:connect",{"id":"IZTTPidF121JCzf9AAAO"}] as {"type":2,"nsp":"/color","data":["user:connect",{"id":"IZTTPidF121JCzf9AAAO"}]} +1ms
browser.js:133
socket.io-client:socket emitting event ["user:connect",{"id":"IZTTPidF121JCzf9AAAO"}] +3ms

Laravel Echo not listening for pusher events

Trying to create a kind of chat app with laravel and vuejs.
Once the message is sent, I fire the event from laravel which reflects on the pusher debug console with the right event class but the listen callback from vuejs is not called at all.
created () {
window.Echo.channel('chat')
.listen('MessageSent', (e) => {
console.log(e); //not getting this
this.sentMessages.push({
message: e.message.message,
user: e.user
});
});
},
Below is a screenshot of the debug console from pusher
see the image here as am told I can't embed images yet
Try this:
created () {
window.Echo.channel('chat')
.listen('App\\Events\\Chats\\MessageSent', (e) => {
console.log(e);
this.sentMessages.push({
message: e.message.message,
user: e.user
});
});
},
By default, Laravel will broadcast the event using the event's class name. However, you may customize the broadcast name by defining a broadcastAs method on the event:
public function broadcastAs()
{
return 'server.created';
}
The above was copy pasted from Laravel Broadcast Name
My recommendation:
I have always used private channels for chat and you must too.
Read here why

Twilio awaits response, I don't want server to respond

I am using a Slack webhook to process incoming SMS messages from Twilio. However, the way I have it set up, It seems that Twilio is expecting the web server (slack) to respond to it. This causes errors to be generated in Twilio, and I obviously don't want errors because I'll be getting emails.
I am using the twilio-ruby gem in Ruby to send out the SMS messages, and using the slack-ruby-client to monitor incoming messages from Slack.
How do I stop Twilio from trying to expect a response from the web server when it POSTS to the Slack webhook? Is that even possible or do I have this all configured incorrectly?
EDIT
Here's the function that I have which sends the forwarded SMS to Slack:
const https = require("https");
// Make sure to declare SLACK_WEBHOOK_PATH in your Environment
// variables at
// https://www.twilio.com/console/runtime/functions/configure
exports.handler = (context, event, callback) => {
// Extract the bits of the message we want
const { To, From, Body } = event;
// Construct a payload for slack's incoming webhooks
const slackBody = JSON.stringify({
text: `!asi SMS\nFrom: ${From}\nMessage: ${Body}`
});
// Form our request specification
const options = {
host: "hooks.slack.com",
port: 443,
path: context.SLACK_WEBHOOK_PATH,
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": slackBody.length
}
};
// send the request
const post = https.request(options, res => {
// only respond once we're done, or Twilio's functions
// may kill our execution before we finish.
res.on("end", () => {
// respond with an empty message
callback(null, new Twilio.twiml.MessagingResponse());
});
});
post.write(slackBody);
post.end();
};
Twilio developer evangelist here.
Twilio is always going to expect at least a 200 response or will timeout at 15 seconds for incoming message webhooks.
You could avoid the error messages by using something in between Twilio and Slack, like Zapier (example in this blog post) or using a Twilio Function (as described here) or with Twilio Studio (from the documentation here).
Hope one of those ideas helps!
Update
Further to my earlier answer, and given the code you used to make the call, I have an update.
When making a request using Node's built in https module you will not get the end event until you have read the data. This is what is causing the timeout between Twilio and the Twilio Function, you are never responding to it because you don't consume the data from the request.
In a quick test I found that just listening for the data event meant that the end event did fire. So update your function to:
const post = https.request(options, res => {
// only respond once we're done, or Twilio's functions
// may kill our execution before we finish.
res.on("data", () => {});
res.on("end", () => {
// respond with an empty message
callback(null, new Twilio.twiml.MessagingResponse());
});
});
And it should work.

Laravel Echo Server can not be authenticated, got HTTP status 403

I got laravel-echo-server and Laravel 5 application with vuejs, and I'm trying to connect front end to back end via sockets.
I've managed to connect everything together via Echo.channel() method, however it will not subscribe with Echo.private()
This is what I got so far :
Once the page loads I call :
I initilise the Echo via
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001',
csrfToken : Laravel.csrfToken,
auth : {
headers : {
Authorization : "Bearer b6f96a6e99e90dzzzzzzz"
}
}
});
Then I create a new event via vue resourse
Vue.http.get('/api/errors/get');
This fires laravel event(new \App\Events\ErrorsEvent()); event
Which Broadcasts the event privately via
public function broadcastOn()
{
return new PrivateChannel('errors');
}
At this point laravel-echo-server responds with
Channel: private-errors
Event: App\Events\ErrorsEvent
CHANNEL private-errors
Then i try to subscribe to the channel with echo by running
Echo.private('errors')
.listen('ErrorsEvent', (e) => {
this.errors = e.errors;
console.log(e);
});
At which laravel-echo-server responds with
[14:47:31] - xxxxxxxxxxxxxx could not be authenticated to private-errors
Client can not be authenticated, got HTTP status 403
Does anybody know if I'm missing something here?
EDIT
This is my BroadcastServiceProvider
public function boot(Request $request)
{
Broadcast::routes();
/*
* Authenticate the user's personal channel...
*/
Broadcast::channel('App.User.*', function ($user, $userId) {
return (int) $user->id === (int) $userId;
});
}
Also, I've discovered that if I try to subscribe to
Echo.private('App.User.2')
.listen('ErrorsEvent', (e) => {
this.errors = e.errors;
console.log(e);
});
It connects and everything is ok, however it still refuses to connect with the errors channel
My issue was that I hadn't noticed there are two BroadcastServiceProvider::class entries in app/config.php
I had only checked the first one. Once I uncommented App\Providers\BroadcastServiceProvider::class I didn't need to specify the bearer token.
I believe the reason you couldn't connect on the errors channel in your above config is that you need to change your call in your BroadcastServiceProvider (or routes/channels.php) to
Broadcast::channel('errors', function ($user) {
return true; //replace with suitable auth check here
});

Resources