Authorizing Private Event Channels (not triggering WebSocket server listener). Public events work! - Laravel 5.5

Posted 1 year ago by cdr95985

I have implemented a Socket.IO Server with my Laravel 5.5 Application. I am able to broadcast and update the view to all connected clients using public events. However, when I try using private events, it seems that these are not triggering the listener on my socket.io server.

What is happening now from and end-user standpoint: When a user connects to the page, the web socket server log knows that a user connected. When firing the event (which occurs when the user hits the page), the event is logged in laravel.log. The event is sent to the queue and in Redis (I can see it in "queues:default" in the Redis db). The Queue Listener is running (manually) and then processes the private event (removing it from the Redis db). The web socket server never catches the broadcasted event over the "private-channel" at this point.

NOTE: The authorization route for "private-channel" NEVER fires off the log as defined!

I've verified that the channel name is spelled correctly in the web socket server, the event class, and the client page.

Below is the relevant code (I think).

TestController.php @ app.com/PrivateEvent


    public function firePrivateEvent()
    {
        $data = [
            'username' => 'Private JonDoe'
        ];
        
        // This is firing but not getting caught by socket.io
        event(new \App\Events\PrivateEvent($data));
        return view('test.redis');
    }

PrivateEvent.php

The log message in here is getting fired.


namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Support\Facades\Log;

class PrivateEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $data;
            
    /**
     * Create a new event instance.
     *
     * Data passed in will be serialized, along with any public properties
     * 
     * @return void
     */
    public function __construct($data)
    {
        //
        $this->data = $data;
        
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        //return new PrivateChannel('test-channel');
        Log::Info("[Event Raised]: PrivateEvent on private-channel");
        return new PrivateChannel('private-channel');
    }
}

channels.php

This log message is never recorded.


Broadcast::channel('private-channel', function($user) {
    Log::Info("Authorizing private-channel event");
    return 0;
});

BroadcastingServiceProvider.php


namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Broadcast;

class BroadcastServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Broadcast::routes();

        require base_path('routes/channels.php');
    }
}

websocketserver.js

The logs here are not getting fired when broadcasting across the private-channel, but they do when broadcasting across the public-channel.


// subscribe to channels in which we want to notify clients on when updated     
redis.subscribe('public-channel');
redis.subscribe('private-channel');

redis.on('message', function(channel, message){
    //console.log(channel, message);
    
    message = JSON.parse(message);
    console.log('-------------------')
    console.log("MSG FIRED");
    console.log('message channel: ' + channel);
    console.log('message event: ' + message.event);
    console.log(message);
    console.log('emit to: ' + channel + ':' + message.event);
//    io.emit(channel + ':' + message.event, message.data); //test-channel:UserSignedUp
      io.emit(message.event, channel, message.data); //test-channel:UserSignedUp
    console.log('-------------------')
});

client_view.blade.php

Obviously we never get this far with the private-channel, but we do with the public-channel. This page has the CSRF token embedded, as well as the client side socket.io library and the compiled typescript "app.js" where Echo is defined in.


    new Vue({
        el: '#users',
        data: {
            users: ["t1", "t2"]
        },
        mounted: function(){
            console.log("Vue is mounted!");
            
            Echo.channel('public-channel')
             .listen('PublicEvent', (e) => {
                 console.log("[GOT PUBLIC EVENT]:");
                 console.log(e);
                 this.users.push(e);
             });
             
            Echo.private('private-channel')
             .listen('PrivateEvent', (e) => {
                 console.log("[GOT PRIVATE EVENT]:");
                 console.log(e);
                 this.users.push(e);
             })
        }
    });

I'm unsure of where to debug next. Can anyone help me? Thanks!

Please sign in or create an account to participate in this conversation.