Laravel Echo с Pusher не получает сообщения на частном канале - PullRequest
0 голосов
/ 23 декабря 2019

Каждый раз, когда я переключаюсь на частный канал, в браузере ничего не получается, но при использовании только стандартного канала это работает. Моя текущая настройка включает в себя приложение Vue CLI для внешнего интерфейса и Laravel API в качестве внутреннего интерфейса, использующего Laravel Passport для аутентификации.

Этот код используется для подключения к 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 Dashboard Connected

А затем после стрельбыотключение события от маршрута /:

Queue

Наконец, Pusher берет событие и на консоли ничего не отображается:

Output

Однако, если я изменю new PrivateChannel(...) на new Channel(...), а затем использую Echo.channel вместо Echo.private, он начнет отображать что-то в консоли.

Кто-нибудь знает, почему это может происходить?


Обновление, я нашел эту веб-страницу: Pusher Docs -Отладка

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... может быть причиной проблемы, но единственные вещи, которые я мог найти на ней, были:

  1. Изменить наBROADCAST_DRIVER=pusher
  2. Попытка этого кода в 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

Конфигурация My 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
  • Pusher Server

Vue:

  • Установка TypeScript
  • Мой пользовательский обертка HTTP (просто упаковка fetch & axios)

И это работает, так что мне просто придетсяузнайте, что я сделал по-другому, и посмотрите, смогу ли я решить это таким образом. Если вы хотите увидеть этот тестовый код, я поместил его в этот репозиторий.

https://github.com/kingga/stackoverflow-59449785

1 Ответ

0 голосов
/ 26 декабря 2019

Как всегда, это было действительно простое решение, которое упустили из виду.

У меня было два 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');
    }
  },
);
...