Laravel Echo with Pusher 未在私有频道上接收消息
Laravel Echo with Pusher not receiving messages on private channel
每次我切换到私人频道时,浏览器上什么都收不到,但是当只使用标准频道时它就可以了。我当前的设置包括前端的 Vue CLI 应用程序和使用 Laravel Passport 进行身份验证的 Laravel API 作为后端。
这是用于连接 Pusher 的代码。
import LaravelEcho from 'laravel-echo';
// ...
export const Echo = new LaravelEcho({
broadcaster: 'pusher',
key: pusherKey,
cluster,
encrypted: true,
});
Echo.connector.pusher.config.authEndpoint = `${baseURL}/broadcasting/auth`;
store.watch((state: any) => state.$auth.token, (token: string) => {
Echo.connector.pusher.config.auth.headers['Authorization'] = `Bearer ${token}`;
});
store.watch((state: any) => state.$auth.user, (n: any, o: any) => {
if (n) {
console.log(`App.User.${n.id}`); // This is being logged to the console App.User.1
Echo.private(`App.User.${n.id}`)
.listen('.friend.request', (e: any) => {
console.log({ e });
});
}
});
这是频道路由文件:
<?php
Broadcast::channel('App.User.{id}', function ($user, $id) {
return true;
// return (int) $user->id === (int) $id;
});
活动的简化版。
<?php
namespace App\Events;
// ...
class FriendRequestSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
// ...
public function broadcastOn()
{
return new PrivateChannel("App.User.{$this->friend->id}");
}
// ...
}
并且我设置了这条测试路线:
<?php
Route::get('/', function (Request $request) {
event(new FriendRequestSent(User::find(1), User::find(1)));
});
在 运行 Echo.private()...
代码之后,我可以在我的 Pusher 仪表板中看到以下内容:
然后从 /
路线触发事件后:
最后,Pusher 接收到事件并且控制台中没有任何显示:
但是,如果我将 new PrivateChannel(...)
更改为 new Channel(...)
,然后使用 Echo.channel
而不是 Echo.private
,它将开始在控制台中显示一些内容。
有谁知道为什么会这样?
对此的更新,我找到了这个网页:Pusher Docs - Debugging
Pusher : : ["Event sent",{"event":"pusher:subscribe","data":{"auth":"some_auth_code_returned_from_api_broadcasting_auth","channel":"private-App.User.1"}}]
Pusher : : ["Event recd",{"event":"pusher_internal:subscription_succeeded","channel":"private-App.User.1","data":{}}]
Pusher : : ["No callbacks on private-App.User.1 for pusher:subscription_succeeded"]
我可以从最终输出中看出 No callbacks on private-App.User.1...
可能是导致问题的原因,但我唯一能找到的是:
- 改为
BROADCAST_DRIVER=pusher
- 正在
channels.php
中尝试此代码:
<?php
// Notice {userId} rather than {id}.
Broadcast::channel('App.User.{userId}', function ($user, $userId) {
return (int) $user->id === (int) $userId;
});
我现在用 Socket.IO 尝试了这个,我得到了相同的结果:
Socket.IO 控制台输出:
[6:36:11 AM] - Preparing authentication request to: http://isapi.test
[6:36:11 AM] - Sending auth request to: http://isapi.test/api/broadcasting/auth
[6:36:12 AM] - gT9--_C_2c-KwoxLAAAE authenticated for: private-App.User.1
[6:36:12 AM] - gT9--_C_2c-KwoxLAAAE joined channel: private-App.User.1
我的Socket.IO配置:
import io from 'socket.io-client';
(window as any).io = io;
export const Echo = new LaravelEcho({
broadcaster: 'socket.io',
host: `${baseURL.substr(0, baseURL.length - 4)}:6001`,
encrypted: true,
});
Echo.connector.socket.io.opts.authEndpoint = `${baseURL}/broadcasting/auth`;
store.watch(
(state: any) => state.$auth.token,
(token: string) => {
Echo.connector.socket.io.opts.auth.headers.Authorization = `Bearer ${token}`;
},
);
所以我创建了一个完全全新的 Vue 安装,Laravel 具有以下依赖项:
Laravel:
- 护照
- 巴里 CORS
- 推送服务器
Vue:
- TypeScript 安装
- 我的自定义 HTTP 包装器(仅包装 fetch 和 axios)
而且它有效,所以我只需要找出我所做的不同之处,看看我是否可以那样解决它。如果您想查看此测试代码,我已将其放在此存储库中。
一如既往,这是一个非常简单的解决方案,但被忽略了。
我有两个 store.watch
;一个在令牌上,一个在用户上。用户一必须先有 运行 然后令牌一 运行 导致令牌在连接到私人频道时不被设置。例如
store.watch(
(state: any) => state.$auth.token,
(token: string) => {
Echo.connector.pusher.config.auth.headers.Authorization = `Bearer ${token}`;
},
);
store.watch(
(state: any) => state.$auth.user,
(n: any, o: any) => {
if (n) {
// Added this line to fix the issue.
Echo.connector.pusher.config.auth.headers.Authorization = `Bearer ${store.state.$auth.token}`;
Echo.private(`App.User.${n.id}`).listen(
'.friend.request',
(data: any) => {
// store.state.$friends.requests = data;
console.log({ data });
},
);
} else if (o) {
Echo.private(`App.User.${o.id}`)
.stopListening('.friend.request');
}
},
);
每次我切换到私人频道时,浏览器上什么都收不到,但是当只使用标准频道时它就可以了。我当前的设置包括前端的 Vue CLI 应用程序和使用 Laravel Passport 进行身份验证的 Laravel API 作为后端。
这是用于连接 Pusher 的代码。
import LaravelEcho from 'laravel-echo';
// ...
export const Echo = new LaravelEcho({
broadcaster: 'pusher',
key: pusherKey,
cluster,
encrypted: true,
});
Echo.connector.pusher.config.authEndpoint = `${baseURL}/broadcasting/auth`;
store.watch((state: any) => state.$auth.token, (token: string) => {
Echo.connector.pusher.config.auth.headers['Authorization'] = `Bearer ${token}`;
});
store.watch((state: any) => state.$auth.user, (n: any, o: any) => {
if (n) {
console.log(`App.User.${n.id}`); // This is being logged to the console App.User.1
Echo.private(`App.User.${n.id}`)
.listen('.friend.request', (e: any) => {
console.log({ e });
});
}
});
这是频道路由文件:
<?php
Broadcast::channel('App.User.{id}', function ($user, $id) {
return true;
// return (int) $user->id === (int) $id;
});
活动的简化版。
<?php
namespace App\Events;
// ...
class FriendRequestSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
// ...
public function broadcastOn()
{
return new PrivateChannel("App.User.{$this->friend->id}");
}
// ...
}
并且我设置了这条测试路线:
<?php
Route::get('/', function (Request $request) {
event(new FriendRequestSent(User::find(1), User::find(1)));
});
在 运行 Echo.private()...
代码之后,我可以在我的 Pusher 仪表板中看到以下内容:
然后从 /
路线触发事件后:
最后,Pusher 接收到事件并且控制台中没有任何显示:
但是,如果我将 new PrivateChannel(...)
更改为 new Channel(...)
,然后使用 Echo.channel
而不是 Echo.private
,它将开始在控制台中显示一些内容。
有谁知道为什么会这样?
对此的更新,我找到了这个网页:Pusher Docs - Debugging
Pusher : : ["Event sent",{"event":"pusher:subscribe","data":{"auth":"some_auth_code_returned_from_api_broadcasting_auth","channel":"private-App.User.1"}}]
Pusher : : ["Event recd",{"event":"pusher_internal:subscription_succeeded","channel":"private-App.User.1","data":{}}]
Pusher : : ["No callbacks on private-App.User.1 for pusher:subscription_succeeded"]
我可以从最终输出中看出 No callbacks on private-App.User.1...
可能是导致问题的原因,但我唯一能找到的是:
- 改为
BROADCAST_DRIVER=pusher
- 正在
channels.php
中尝试此代码:
<?php
// Notice {userId} rather than {id}.
Broadcast::channel('App.User.{userId}', function ($user, $userId) {
return (int) $user->id === (int) $userId;
});
我现在用 Socket.IO 尝试了这个,我得到了相同的结果:
Socket.IO 控制台输出:
[6:36:11 AM] - Preparing authentication request to: http://isapi.test
[6:36:11 AM] - Sending auth request to: http://isapi.test/api/broadcasting/auth
[6:36:12 AM] - gT9--_C_2c-KwoxLAAAE authenticated for: private-App.User.1
[6:36:12 AM] - gT9--_C_2c-KwoxLAAAE joined channel: private-App.User.1
我的Socket.IO配置:
import io from 'socket.io-client';
(window as any).io = io;
export const Echo = new LaravelEcho({
broadcaster: 'socket.io',
host: `${baseURL.substr(0, baseURL.length - 4)}:6001`,
encrypted: true,
});
Echo.connector.socket.io.opts.authEndpoint = `${baseURL}/broadcasting/auth`;
store.watch(
(state: any) => state.$auth.token,
(token: string) => {
Echo.connector.socket.io.opts.auth.headers.Authorization = `Bearer ${token}`;
},
);
所以我创建了一个完全全新的 Vue 安装,Laravel 具有以下依赖项:
Laravel:
- 护照
- 巴里 CORS
- 推送服务器
Vue:
- TypeScript 安装
- 我的自定义 HTTP 包装器(仅包装 fetch 和 axios)
而且它有效,所以我只需要找出我所做的不同之处,看看我是否可以那样解决它。如果您想查看此测试代码,我已将其放在此存储库中。
一如既往,这是一个非常简单的解决方案,但被忽略了。
我有两个 store.watch
;一个在令牌上,一个在用户上。用户一必须先有 运行 然后令牌一 运行 导致令牌在连接到私人频道时不被设置。例如
store.watch(
(state: any) => state.$auth.token,
(token: string) => {
Echo.connector.pusher.config.auth.headers.Authorization = `Bearer ${token}`;
},
);
store.watch(
(state: any) => state.$auth.user,
(n: any, o: any) => {
if (n) {
// Added this line to fix the issue.
Echo.connector.pusher.config.auth.headers.Authorization = `Bearer ${store.state.$auth.token}`;
Echo.private(`App.User.${n.id}`).listen(
'.friend.request',
(data: any) => {
// store.state.$friends.requests = data;
console.log({ data });
},
);
} else if (o) {
Echo.private(`App.User.${o.id}`)
.stopListening('.friend.request');
}
},
);