echo: Redis keyPrefix Problem

  • Echo Version: 1.5.3
  • Laravel Version: 5.8.*
  • PHP Version: 7.2.17
  • NPM Version: 6.8.0
  • Node Version: 8.10.8

Description:

When Echo used with Redis, it produces keyPrefix to every channel you created. (which is by default “laravel_database_”)

Steps To Reproduce:

1-) Use Redis as Broadcast Driver and Queue Connection

BROADCAST_DRIVER=redis
QUEUE_CONNECTION=redis

2-) Create any Event

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

    public $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function broadcastOn()
    {
        return new PrivateChannel('test');
    }

    public function broadcastAs()
    {
        return 'user.registered';
    }

    public function broadcastWith()
    {
        return ['id' => $this->user->id];
    }
}

3-) Broadcast this event with Private Channel called ‘test’ 4-) Authorize this channel

Broadcast::channel('test', function ($user) {
    return $user;
});

5-) Initialize Echo in your js file

import Echo from "laravel-echo"

window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname + ':6001',
    authEndpoint: "/broadcasting/auth",
});

6-) Initialize your channel

 Echo.private(`test`)
                .listen('.user.registered', function (e) {
                    console.log(e);
                });

7-) Send event

event(new UserRegistered($user));

😎 See laravel-echo-server logs

[6:13:51 AM] - W3drJJWfqL9OacTmAAAa authenticated for: private-test
[6:13:51 AM] - W3drJJWfqL9OacTmAAAa joined channel: private-test
Channel: foo_bar_database_private-test
Event: user.registered

My Redis keyPrefix is “foo_bar_database_”, so the channel name that the event emitted is “foo_bar_database_private-test” but i am listening the channel “private-test”. So Echo never gets the event.

I tried to delete “private-” prefixes from both php&js side but this time Echo not requiring to authenticate channel anymore since not see as private channel.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 12
  • Comments: 20 (5 by maintainers)

Most upvoted comments

I was able to get it working:

In config/database.php disable prefix for redis.

Now i can do

 window.Echo.private('channel')

And in routes/channels.php

Broadcast::channel('channel', function ($user) {

With redis-cli monitor 👍

1558979801.909666 [0 172.20.0.1:35198] "PUBLISH" **"private-channel"** "{\"event\":\"App\\\\Events\\\\PrivateMessage\",\"data\":{\"msg\":\"Hello\",\"user\":\"foo\",\"socket\":\"vDVEap6hCjgJ5OhtAAAB\"},\"socket\":\"vDVEap6hCjgJ5OhtAAAB\"}"

And Echo clients gets their message.

As you’re using Laravel just edit your .env file and set:

REDIS_PREFIX=

This will remove the ‘foo_bar_database_’ prefix from your channel names. Then make sure you’ve restarted your services.

@eightyfive I found the solution.

On your larave-echo-server.json file

"databaseConfig": {
	"redis": {
		"keyPrefix": "your_prefix_database_"
	},
}

On your js files

Echo.channel('your-channel-name').listen('YourEventName', (event) => {
    console.log(event);
});

Same problem here.

Echo.private will add a prefix private- to channel’s name.

So Laravel adds laravel_database_private-channel prefix and

Echo.private(laravel_database_private-channel) will add another prefix like so:

private- laravel_database_private-channel

And Echo will not get the event never becouse it’s listening on other channel.

It can be fixed by below steps. 1-) Remove all "‘private-’ + " prefixes in your compiled Echo.js This will make your channel name not being prefixed with “private-”. 2-) At the backend part, authorize your channels in routes/channels.php as follows Add your prefix to channel name.

Broadcast::channel('foo_bar_database_private-test', function ($user) {
   return true;
});

3-) At the frontend part, register your channels as follows Add your prefix to channel name. Your channel name will not be prefixed with “private-”.

Echo.private(`foo_bar_database_private-test`)
                .listen('.user.registered',function (e) {
                    console.log(e);
                });

4-) Broadcast event and see console output for laravel-echo-server

[7:19:56 AM] - 5KykLGFS9kiYu8pFAAAF authenticated for: foo_bar_database_private-test
[7:19:56 AM] - 5KykLGFS9kiYu8pFAAAF joined channel: foo_bar_database_private-test
Channel: foo_bar_database_private-test
Event: user.registered

5-) As you can see, the channel names match.

To solve this bug, Private(“private-”) and Presence(“presence-”) prefixes should not be mandatory.

Problem was caused by [6.x] Fix channel names when broadcasting via redis, not by databaseConfig.redis.keyPrefix which is well-documented.

same issue, keyPrefix in echo options needed =(

I know this is closed but I disagree that this is a framework issue. The echo server should be configurable such that if there is a prefix it can be prepended to the names of the keys. If this is how Laravel writes to redis, why should this not support that prefix?

It tends to default to strtolower(Str::snake(config('app.name')))

Do you actually need the Redis prefix in this situation?