How to troubleshoot Laravel Broadcasts + Pusher..? - laravel

I'm following the Laravel Documentation to set up broadcasting using Pusher, and it looks pretty straight-forward, but I haven't gotten it work yet, so I must have made a mistake somewhere along the way.
Here's what I've done:
Server Side
I've created an Event that implements the ShouldBroadcastNow interface and defined the broadcastsOn() method.
class ThreadMessageCreated implements ShouldBroadcastNow {
use Dispatchable, InteractsWithSockets, SerializesModels;
public function broadcastOn() {
return new Channel('bobtest');
}
I'm raising the Event from one of my API Controllers:
public function createMessage(Thread $thread, Request $request) {
...
event(new ThreadMessageCreated($message, $thread));
return $message;
}
I've configured my pusher credentials in my .env file.
Client Side
I've configured Laravel Echo on the Client side (via the angular-laravel-echo package) and subscribed my client to the channel.
ngOnInit() {
this.echo
.join('bobtest', 'public')
.listen('bobtest', 'ThreadMessageCreated')
.subscribe(()=>alert('message received'));
console.log(this.echo);
}
However, when my API endpoint is hit, the event is fired, but I don't see anything on the client side.
So, I added logging in the broadcastOn() method to verify it's getting called. Then I changed the driver from pusher to log and I do see the Broadcast info getting written to the laravel.log file.
So, I'm assuming that the broadcast is also happening when using the Pusher driver, and either isn't being sent out from Laravel, or isn't being received by the Client.
I'm new to sockets, pusher, & Laravel Echo, so I'm not sure where to look for more info to track this down.
I don't see any errors in the laravel.log file.
I don't see any errors in Chrome Dev Tools on the client side.
I logged into pusher and there are no errors in the 'Error Logs' tab
What can I do to get more details to figure out where the problem is occurring?
Thanks! :-)
[UPDATE]
I can see the broadcasts are appearing in my pusher account, so the problem seems to be on the client side. Perhaps I'm not subscribing correctly to the right channel?
Also, I'm using Laravel as the back end only, using JWT Authentication. I'm currently not using the laravel csrf token, not sure if that could pertinent or not.

I now learned I can see web socket data in Dev Tools. I'm assuming this error was there before, I just didn't notice it. I guess the 101 status code didn't stand out to me :-o
But after looking in Dev Tools, I could clearly see this error:
{
message: "App key xxx not in this cluster. Did you forget to specify the cluster?",
event: "pusher:error"
}
To view Web Socket activity:
Dev Tools > Network > Filter > WS (Web Sockets):
In my case, I simply needed to specify the cluster in the Laravel Echo config:
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'xxxxxxxxxxxxxxxxxxxx',
cluster: 'us2', <--------------[pusher needs a cluster :-)]
host: 'http://the-host.com',
auth: {
headers: {
'Authorization': 'Bearer ' + token
}
}
});

Related

Serverless WebSocket route responses

I am using serverless to create a WebSocket service, for which I am able to successfully trigger my WebSocket routes locally, using serverless-offline and for the deployed service.
The issue I am having now is responding to those WS events.
I am able to use AWS.ApiGatewayManagementApi.postToConnection to respond to my local WebSocket events, though I cannot seem to get the return value of my handler to actually send a WebSocket event in response, as these serverless-offline docs and these AWS docs suggest.
The serverless.yml route:
ws-custom:
handler: handler.wsCustom
events:
- websocket:
route: custom
routeResponseSelectionExpression: $default
The handler:
module.exports.wsCustom = async (event) => {
const body = JSON.parse(event.body);
console.log('WebSocket `custom` event!', event);
return {
statusCode: 200,
body: JSON.stringify({ message: `Hello, ${body.name}!` }),
};
}
Invoking the function in my browser JavaScript:
ws.send(JSON.stringify({ 'action': 'custom', 'name': 'kevbot' }));
The result is that my serverless-offline logs (or CloudWatch in the case of the deployed project) will create an event with the log successfully, but my client will receive no events in response.
Does anyone know how I can do this with the return value of the handler?
EDIT:
The problem seems to exist within my serverless-offline setup. I will attempt to get it working locally and will create an issue necessary.
An important point to note when using WebSocket APIs and trying to return a response from your integration back to the client, as mentioned in this doc:
For a route that is configured to use AWS_PROXY or LAMBDA_PROXY integration, communication is one-way, and API Gateway will not pass the backend response through to the route response automatically. For example, in the case of LAMBDA_PROXY integration, the body that the Lambda function returns will not be returned to the client. If you want the client to receive integration responses, you must define a route response to make two-way communication possible.
So, if you are using a proxy integration, then you cannot return a response back to the client. You would have to use the AWS.ApiGatewayManagementApi.postToConnection method to communicate any data.
Alternatively, if you are using a non-proxy integration, then you can set up a route response for your integration.

Connect Laravel echo from Angular project

I have a Laravel-echo-server with Redis running on my local.
I created a test API endpoint, that emits broadcastable event.
on http://localhost:8000/api/web-socket-test I see the response in echo server CLI.
I set-up laravel-echo auth key and I can get the stat info from server API
http://localhost:6001/apps/APP_ID/status?auth_key=b73a61d0.
The problem is with connecting to echo-server from Angular via ws: protocol.
My connection code is
import {webSocket, WebSocketSubject} from 'rxjs/webSocket';
export class MyComponent implements OnInit, OnDestroy {
myWebSocket: WebSocketSubject<any> = webSocket('ws://127.0.0.1:6001');
ngOnInit() {
this.myWebSocket.subscribe(
msg => console.log('message received: ' + msg),
err => console.log(err),
() => console.log('complete')
);
}
And finally I've got an error: WebSocket connection to 'ws://127.0.0.1:6001/' failed: Connection closed before receiving a handshake response.
How can I establish ws connection?
I believe you want to try connecting using the socket.io client libraries instead of using rxjs raw websockets.
Although it's not immediately clear from the laravel echo server docs, the project title states it's a 'Socket.io server for Laravel Echo'. So I'm assuming you should use the socket.io client libraries for connections.

Laravel listen socket.io client emit

I have chat application using Laravel + laravel-echo-server + Redis.
currently i am using http api request from client to send message.
But its slow if i have large client number.
Is there a way to send message from client to server through socket and listen in laravel?
Probably something like this
public function onMessage($client, $data)
{
.....
}
i already tried laravel-websocket, but if i set APP_DEBUG=false in .env CustomSocketHandler unable to work anymore.
Thank you.

Blockcypher Websocket endpoint not working

I am using the Blockcypher API for test bitcoin transactions and I have troubles with the websocket API endpoint.
When sending the regular ping object after creating a new Websocket it works fine:
this.ws.onopen = () => {
this.ws.send(JSON.stringify({"event": "ping"}))
but when trying to check the confidence of a transaction like this we get an error
this.ws.onopen = () => {
this.ws.send(JSON.stringify({event: 'tx-confidence', address:'<bitcoin address as string>', confidence:0.9}))
Is there anything wrong with the datatypes? Any help would be great!
API reference
Event reference
You probably reached the limit. Consider adding your BlockCypher token at the end of the websocket URL. This was somehow forgotten in the documentation.

sails.js + socket.io: Can't receive standard sail.js/socket.io messages on client

With the newest beta version from sails.js (0.10.0-rc5) I'm trying to do this:
sails new Test
cd Test
sails generate api user
Create file assets/js/test.js
var socket = io.connect('http://localhost:1337');
socket.on('connect',function() {
console.log('connected');
socket.request('/user',{}, function(users) {
console.log(users);
});
socket.on('message', function(msg) {
console.log("Message: " + msg);
});
socket.on('user', function(msg) {
console.log("User: " + msg);
});
});
My problem
console.log("User: " + msg); and console.log("Message: " + msg); aren't receiving any messages when I create or update a user.
According to the documentation and to the Intro to sails.js video this socket.io messages should be send automatically.
What am I missing to successfully receive sails.js/socket.io message on my client?
If you installed the latest NPM version, then you'll also have the latest version of the Sails socket client. Check out its page on Github for basic usage, then check out the PubSub section of the Sails migration guide, which explains the differences between Sails v0.9.9x (which the Intro to Sails.js video shows) and the latest version. In the end, your code should look more like:
// Note--the latest sails socket client connects automatically!
// Get all of the existing users--also subscribes to socket events
// for those users
io.socket.get('/user', function serverResponded (body, sailsResponseObject) {
console.log(body);
});
// When a socket message about a user is received, display it
io.socket.on('user', function(data) {
console.log(data);
});
Notes
Pay special attention to the section in the migration guide about .watch(); it means that you don't get create events automatically anymore and have to subscribe to them in your server code using (for the User model) User.watch().
Remember that in general you don't get socket messages about actions that you yourself trigger, so if you want to test that your message-handling code is working, it's best to open up two windows (or tabs) and do your requests in one while watching for events in the other.
Also remember that you only get subscribed to socket events when you make a socket request; an AJAX call to /users will retrieve all of the current users, but you won't be subscribed to events. It has to be done using io.socket.get.

Resources