I used laravel websockets with echo and pusher js. this is my code:
bootstrap.js:
import Echo from 'laravel-echo'
window.Pusher = require('pusher-js');
window.Pusher.Runtime.createXHR = function () {
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
return xhr;
};
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
encrypted: false,
wsHost: window.location.hostname,
wsPort: 6001,
wssPort: 6001,
});
broadcasting.php:
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => false,
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'https',
'curl_options' => [
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
]
],
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
websockets.php
'ssl' => [
/*
* Path to local certificate file on filesystem. It must be a PEM encoded file which
* contains your certificate and private key. It can optionally contain the
* certificate chain of issuers. The private key also may be contained
* in a separate file specified by local_pk.
*/
'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),
/*
* Path to local private key file on filesystem in case of separate files for
* certificate (local_cert) and private key.
*/
'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),
/*
* Passphrase for your local_cert file.
*/
'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
],
everything works correctly running on localhost. But when i try to run it on the server, i get this error messages on echo listener page console: (ubuntu server + ssl)
WebSocket connection to 'wss://example.com/app/ZLZVrjyIVjiXlUCF?protocol=7&client=js&version=5.0.0&flash=false' failed: Error during WebSocket handshake: Unexpected response code: 404
OPTIONS https://sockjs-mt1.pusher.com/pusher/app/ZLZVrjyIVjiXlUCF/963/qo637plk/xhr_streaming?protocol=7&client=js&version=5.0.0&t=1569413857094&n=1 404 (Not Found)
Access to XMLHttpRequest at 'https://sockjs-mt1.pusher.com/pusher/app/ZLZVrjyIVjiXlUCF/963/qo637plk/xhr_streaming?protocol=7&client=js&version=5.0.0&t=1569413857094&n=1' from origin 'https://example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
and repeats every 3 secs! do u have any idea for solving this?! :(
in my case, I added to config/cors.php the following
'paths' => ['api/v1/*', 'stats/*', 'broadcasting/auth'],
and identified the authEndpoint since pusher is running on another server
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
forceTLS: JSON.parse(process.env.MIX_PUSHER_APP_FORCE_TLS),
wsHost: process.env.MIX_PUSHER_WS_HOST,
wsPort: 6001,
enabledTransports: ['ws', 'wss'],
authEndpoint: 'http://127.0.0.1:8000/broadcasting/auth',
auth: {
headers: {
Authorization: 'Bearer ' + localStorage.getItem('MY-AUTH-TOKEN')
}
}
I solved this problem by changing pusher-js version from 6.0.0 to 5.1.1. in (Laravel vuejs project)
pusher v4.0
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,
wsHost: window.location.hostname,
forceTLS: false,
wsPort: 6001,
disableStats: true,
enabledTransports: [''],
});
Solved my problem
Related
I am trying to check new notification message and show it to realtime on "bell icon with count"
Everything works as expected in Localhost, but in server the layout file cannot receive data for further implementation
"pusher/pusher-php-server": "7.0.2",
"beyondcode/laravel-websockets": "^1.13",
Broadcasting configuration
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => false,
'host' => '127.0.0.1', // in server host is different
'port' => 6001,
'scheme' => 'http'
],
'client_options' => [
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
],
],
Notification Class
public function via($notifiable)
{
return ['database', 'broadcast'];
}
public function toArray($notifiable)
{
return [
// this part is for storing notification data to 'DB'
];
}
public function toBroadcast($notifiable)
{
return new BroadcastMessage([]);
}
App Layout
window.onload=function(){
Echo.private('App.Models.User.{{ auth()->id() }}')
.notification((e) => {
console.log('ok');
// here bell icon and notification is refresh using (id).load()
});
};
bootstrap.js
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
wsHost: import.meta.env.VITE_PUSHER_HOST,
wsPort: 6001,
forceTLS: false,
disableStats: true,
cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
});
Data is stored in database, and when refresh the page we can see the latest data.
But when new notification class is called it does not show data to layout file means the console.log() cannot trigger. Any idea for this bug and thanks in advance.
ps: Works in localhost, but not on server..
Please run the command and check
composer dump-autoload
php artisan optimize:clear
May be you are facing Caches in .env file
I've created a chat app, which is working fine on my localhost, but on production event is not being broadcast. I have used a handle to see if event is working as expected but i think it isn't.
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message, $participantId;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($message, $participantId)
{
$this->message = $message;
$this->participantId = $participantId;
}
public function handle() {
dd('Hello WOrld');
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('chat.'
.$this->message->room->id
);
}
}
Where I'm broadcasting my event in controller
public function addMessage(Request $request)
{
$roomId = $request->input('roomId');
$participantId = $request->input('participantId');
if (empty($roomId)) {
$room = ChatRoom::create(['type' => 'chat']);
$roomId = $room->id;
ChatRoomUserRelation::create(
[
'user_id' => Auth::user()->id,
'room_id' => $roomId
]
);
ChatRoomUserRelation::create(
[
'user_id' => $participantId,
'room_id' => $roomId
]
);
}
$userId = Auth::user()->id;
$message = $request->input('message');
$media = [];
$i = 0;
while ($request->file('media' . $i) !== null) {
if (
$request->file('media' . $i)->move(
base_path('public/images/posts/'),
$request->file('media' . $i)->getClientOriginalName()
)
) {
$media[] = $request->file('media' . $i)->getClientOriginalName();
}
$i++;
}
$newMessage = Chat::create([
'messaged_by' => $userId,
'message' => $message,
'media' => json_encode($media)
]);
ChatRoomRelation::create([
'chat_id' => $newMessage->id,
'room_id' => $roomId
]);
$newMessage = $newMessage->load(['user', 'room', 'room.participant']);
broadcast(new MessageSent($newMessage, $participantId));
broadcast(new MessageRecieved($newMessage));
return $newMessage;
}
Broadcasting.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Broadcaster
|--------------------------------------------------------------------------
|
| This option controls the default broadcaster that will be used by the
| framework when an event needs to be broadcast. You may set this to
| any of the connections defined in the "connections" array below.
|
| Supported: "pusher", "ably", "redis", "log", "null"
|
*/
'default' => env('BROADCAST_DRIVER', 'null'),
/*
|--------------------------------------------------------------------------
| Broadcast Connections
|--------------------------------------------------------------------------
|
| Here you may define all of the broadcast connections that will be used
| to broadcast events to other systems or over websockets. Samples of
| each available type of connection are provided inside this array.
|
*/
'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com',
'port' => env('PUSHER_PORT', 443),
'scheme' => env('PUSHER_SCHEME', 'https'),
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'encrypted' => true,
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'http',
'curl_options' => [
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
]
],
'client_options' => [
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
],
],
'ably' => [
'driver' => 'ably',
'key' => env('ABLY_KEY'),
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
];
bootstrap.js
import _ from 'lodash';
import 'bootstrap';
/**
* We'll load the axios HTTP library which allows us to easily issue requests
* to our Laravel back-end. This library automatically handles sending the
* CSRF token as a header based on the value of the "XSRF" token cookie.
*/
import axios from 'axios';
window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
/**
* Echo exposes an expressive API for subscribing to channels and listening
* for events that are broadcast by Laravel. Echo and event broadcasting
* allows your team to easily build robust real-time web applications.
*/
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
wsHost: import.meta.env.VITE_PUSHER_HOST ?? `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
wsPort: 6001,
wssPort: 6001,
cluster:import.meta.env.VITE_PUSHER_APP_CLUSTER,//added this line
forceTLS: false,
disableStats: true,
enabledTransports: ['ws', 'wss'],
});
A function in my component to listen broadcasted event
joinChatChannel() {
this.chatChannel = window.Echo.private(`chat.${this.activeRoomId}`)
//listening for channel whisper
this.chatChannel.listenForWhisper('typing', user => {
this.placeholder = user.first_name + ' is typing...'
if (this.typingTimer) {
clearTimeout(this.typingTimer);
}
this.typingTimer = setTimeout(() => {
this.placeholder = '';
}, 500);
})
//listening which gets fired on message sent
this.chatChannel.listen('MessageSent', (e) => {
this.roomChats.push(e.message);
if (this.activeRoomId == 0) {
this.rooms.push(e.message.room);
this.activeRoomId = e.message.room.id;
}
})
}
Project is deployed on VPS, and made live on an ip, but websocket configured to run on localhost, same scenario is wokring on on my own pc, but not in VPS, let me know If I'm missing something here or you may require to see any file, please help me I've tried so many things through but nothing worked, I know this question might be duplicated but issue seems different.
developer network table
I have tried to reinstall my operating system, reinstall laravel, reinstall all the dependencies, checked out the websocket logs, there was no broadcasted event listed, checked websocket dashboard stats.
I try to use laravel-websockets in Larave l9/Inertiajs2 / vuejs3 and for that
in resources/js/bootstrap.js I filled lines :
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, // need on live
swHost : window.location.hostname,
swPort : 601,
forceTLS: true
});
But when in vue file I try to catch event with code :
Echo.private('home')
.listen('NewMessage', (e) => {
console.log('chatInit NewMessage e::')
console.log(e)
}
)
I run command in tinker :
event(new \App\Events\NewMessage("Hello world123 987"))
I see this event in local-server.com/laravel-websockets
but in the console I got error :
POST http://local-server.com/broadcasting/auth 404 (Not Found)
In app/Providers/BroadcastServiceProvider.php I added option :
public function boot()
{
// Broadcast::routes();
Broadcast::routes(['middleware' => ['auth:sanctum']]);
require base_path('routes/channels.php');
}
and in routes/web.php (I looged in and opened page below):
Route::prefix('manager')->name('manager.')->middleware(['auth:sanctum', 'verified', 'CheckIsManager' ])->group(function() {
Route::get('dashboard/index', [ManagerDashboardController::class, 'index'])->name('dashboard.index');
...
In app/Events/NewMessage.php I have :
public function broadcastOn()
{
return new PrivateChannel('home');
}
In config/broadcasting.php :
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
// 'encrypted' => true, // need on live
'host'=>'local-todo-list.com',
'port'=>6001,
'scheme'=>'http',
],
'client_options' => [
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
],
],
Did I miss some options ?
Thanks in advance!
I am banging my head for a couple of hours already because when i deploy my websockets in production server, it wont work. I keep on having this error: Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT.
These are my configuration:
In websockets.php
return [
/*
* Set a custom dashboard configuration
*/
'dashboard' => [
'port' => env('LARAVEL_WEBSOCKETS_PORT', 6002),
],
/*
* This package comes with multi tenancy out of the box. Here you can
* configure the different apps that can use the webSockets server.
*
* Optionally you specify capacity so you can limit the maximum
* concurrent connections for a specific app.
*
* Optionally you can disable client events so clients cannot send
* messages to each other via the webSockets.
*/
'apps' => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'path' => env('PUSHER_APP_PATH'),
'capacity' => null,
'enable_client_messages' => false,
'enable_statistics' => true,
],
'ssl' => [
/*
* Path to local certificate file on filesystem. It must be a PEM encoded file which
* contains your certificate and private key. It can optionally contain the
* certificate chain of issuers. The private key also may be contained
* in a separate file specified by local_pk.
*/
'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),
/*
* Path to local private key file on filesystem in case of separate files for
* certificate (local_cert) and private key.
*/
'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),
/*
* Passphrase for your local_cert file.
*/
'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
'verify_peer' => false,
],
],
....
In broadcasting.php
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
// 'useTLS' => true, //live
// 'encrypted' => true, //comment out in local
'host' => '127.0.0.1',
'port' => 6002,
'scheme' => 'https', //in live this is https
// 'scheme' => 'http' //in local this is only http,
'curl_options' => [
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SLL_VERIFYPEER => 0
]
],
],
In 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,
forceTLS: true, //for live
// encrypted: false, //local
encrypted: true, //live
wsHost: window.location.hostname,
wsPort: 6002,
wssPort: 6002, //in local, comment this one
// enabledTransports: ['ws','wss'],
disableStats: true
});
I am not sure what i'm doing wrong here but it looks like i've followed all tutorials in the internet but with no avail, i am getting that error.
Thanks.
Apologies, but I was able to solved this by opening the port that I chose to use in the server which in my case it is port 6002. This is a very rookie mistake on my part, as I am not really that great in server stuff.
This is how you open a port How to open some ports on Ubuntu?
Anyway, thank you!
I am having a hard time figuring out how to connect our Laravel app to a websockets server hosted on port 6001. Everything works fine on my local machine, but when I deploy on Kubernetes, I get the following errors in console:
Pusher : : ["Connecting",{"transport":"ws","url":"wss://localhost:443/app/[redacted]?protocol=7&client=js&version=5.1.1&flash=false"}]
app.js:1 WebSocket connection to 'wss://localhost/app/[redacted]?protocol=7&client=js&version=5.1.1&flash=false' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
It makes no sense to me that the url reported by Pusher is wss://localhost:443, but the actual connection is attempting at wss://localhost on port :80.
Furthermore, I've explicitly set enabledTransports: ['ws'], and have not provided a wssHost or wssPort.
Additionally, since this connection is taking place within a Kubernetes pod, I have taken every step to disable SSL. Below are my configs:
config/websockets.php:
...
'apps' => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'path' => env('PUSHER_APP_PATH'),
'capacity' => null,
'enable_client_messages' => false,
'enable_statistics' => true,
],
],
...
resources/js/store/state.js
...
import Echo from 'laravel-echo'
/**
* Echo exposes an expressive API for subscribing to channels and listening
* for events that are broadcast by Laravel. Echo and event broadcasting
* allows your team to easily build robust real-time web applications.
*/
window.Pusher = require('pusher-js');
window.Pusher.logToConsole = true;
let state = {
ads:{},
latestAds: [],
selectedAds: [],
partCodes:[],
carCodes:[],
echo: new Echo({
broadcaster: 'pusher',
key: [redacted],
wsHost: 'localhost',
wsPort: 6001,
disableStats: true,
enabledTransports: ['ws'], // <- added this param
auth: {
headers: {
Authorization: 'Bearer ' + localStorage.getItem('admanager-token'),
'X-CSRF-Token': "CSRF_TOKEN"
}
},
'cluster': 'eu',
})
}
export default state
...
In your config/broadcasting.php, you should try this:
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => false,
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'http',
'encrypted' => false,
],
],
While on front-end make sure three components are in sync:
wsHost
wsPort
and app_key