Laravel-Echo not subscribing to private channels through Vue.js

1.6k Views Asked by At

I'm developing a project with Laravel (back) and Vuejs (with Vuex). I also use Sanctum:auth to authenticate users, laravel-websockets and Laravel-Echo for broadcast.

Before, I had received an authentication problem on my console with the error: "POST 'broadcast / auth' 404 not found".

I was able to solve it after watching a tutorial that combined Sanctum, Vue and Laravel Echo in the same project.

However, now that I test the service, I realize that I can listen to public channels but not private channels.

From what I see on the websockets-dashboard, I don't even subscribe to private channels.

In my archive .vue:

import room from './Room'
import axios from 'axios'
import Echo from 'laravel-echo'
import Pusher from 'pusher-js'
console.log(Pusher);
...
export default {
...
   data: () => ({
        ...
        Echos:undefined
   }),
  
   mounted(){
    ...
    this.instantiatingEcho();
   },
   
   methods:{
   
   ...
   instantiatingEcho(){
   
        axios({
        method: "GET",
        url: "http://127.0.0.1:8000/api/users",
        headers: {
            Authorization: `Bearer ${this.$store.state.user.token}`,
        },
        })
        .then(({ data }) => {
            console.log(data);

            this.Echos = new Echo({
                broadcaster: 'pusher',
                key: process.env.VUE_APP_WEBSOCKETS_KEY,
                wsHost: process.env.VUE_APP_WEBSOCKETS_SERVER,
                wsPort: 6001,
                forceTLS: false,
                disableStats: true,
                authorizer: (channel, options) => {
                    console.log(options);
                    return {
                        authorize: (socketId, callback) => {
                            axios({
                                method: "POST",
                                url: "http://127.0.0.1:8000/api/broadcasting/auth",
                                headers: {
                                    Authorization: `Bearer ${this.$store.state.user.token}`,
                                },
                                data: {
                                    socket_id: socketId,
                                    channel_name: channel.name,
                                },
                            })
                            .then((response) => {
                                callback(false, response.data);
                            })
                            .catch((error) => {
                                callback(true, error);
                            })
                        },
                    }
                }
            })
        })

        this.enterinrom();
    },

    enterinrom(){
        this.Echos.private('Room.2')
        .listen('BroadcastRoom', (e) =>{
            console.log(e)
        });    
    },
    
    }
}

channels.php:

 Broadcast::channel('Room.{id}', function ($id){
     return true;
 });

Event:

 <?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Broadcasting\RoomChannel;

class BroadcastRoom implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    public $mensage;
    public $id;


    public function __construct($mensage, $id)
    {
       $this->mensage = $mensage;
       $this->id = $id;
    }

    public function broadcastWith()
    {
       return ["mensage" => $this->mensage];
    }


    public function broadcastOn()
    {
        return new PrivateChannel('Room.'.$this->id);
    }

}

api.php:

   ...

   Broadcast::routes(['middleware' => ['auth:sanctum']]);

   Route::middleware('auth:sanctum')->get('/users', function (Request $request) {
       return $request->user();
   });

   Route::post('/users/login', function (Request $request) {

   $user = User::where('email', $request->email)->first();

   if (!$user || ($request->password != $user->password)) {
        return response([
            'message' => ['These credentials do not match our records.']
            ], 404);
   }

   $token = $user->createToken('idiot-online-token')->plainTextToken;

   $response = [
        'user' => $user,
        'token' => $token
   ];

   return response($response, 201);
});

web.php:

Route::get('/enviaevento/{id}', function ($id) {
    return event(new \App\Events\BroadcastRoom('Uai só...', $id));
});

App\Providers\BroadcastServiceProvider::class in config/app.php is uncommented.

Results: enter image description here

Someone would can help me?

1

There are 1 best solutions below

1
On

In the authorizer property please make sure that the response is correctly used. You could try to use response instead of response.data. I've been stuck on this problem for a while just to realize that the snippet in the documentation doesn't suffice my situation.

import room from './Room'
import axios from 'axios'
import Echo from 'laravel-echo'
import Pusher from 'pusher-js'
console.log(Pusher);
...
export default {
...
   data: () => ({
        ...
        Echos:undefined
   }),
  
   mounted(){
    ...
    this.instantiatingEcho();
   },
   
   methods:{
   
   ...
   instantiatingEcho(){
   
        axios({
        method: "GET",
        url: "http://127.0.0.1:8000/api/users",
        headers: {
            Authorization: `Bearer ${this.$store.state.user.token}`,
        },
        })
        .then(({ data }) => {
            console.log(data);

            this.Echos = new Echo({
                broadcaster: 'pusher',
                key: process.env.VUE_APP_WEBSOCKETS_KEY,
                wsHost: process.env.VUE_APP_WEBSOCKETS_SERVER,
                wsPort: 6001,
                forceTLS: false,
                disableStats: true,
                authorizer: (channel, options) => {
                    console.log(options);
                    return {
                        authorize: (socketId, callback) => {
                            axios({
                                method: "POST",
                                url: "http://127.0.0.1:8000/api/broadcasting/auth",
                                headers: {
                                    Authorization: `Bearer ${this.$store.state.user.token}`,
                                },
                                data: {
                                    socket_id: socketId,
                                    channel_name: channel.name,
                                },
                            })
                            .then((response) => {
                                callback(false, response);
                            })
                            .catch((error) => {
                                callback(true, error);
                            })
                        },
                    }
                }
            })
        })

        this.enterinrom();
    },

    enterinrom(){
        this.Echos.private('Room.2')
        .listen('BroadcastRoom', (e) =>{
            console.log(e)
        });    
    },
    
    }
}