webman/push

webman/push - это бесплатный серверный плагин для передачи данных, клиентская часть основана на модели подписки, совместима с pusher, и имеет множество клиентских приложений, таких как JS, Android (Java), IOS (Swift), IOS (Obj-C), uniapp, .NET, Unity, Flutter, AngularJS и т. д. SDK для серверной части поддерживает PHP, Node, Ruby, Asp, Java, Python, Go, Swift и т. д. Клиент имеет встроенный механизм поддержания соединения и автоматического переподключения при разрыве, что обеспечивает простое и стабильное использование. Подходит для моментальной передачи сообщений, чатов и многих других сценариев мгновенного общения.

Плагин поставляется с веб-клиентом push.js и клиентским приложением uniapp uniapp-push.js, а для других языков клиентов можно загрузить с сайта https://pusher.com/docs/channels/channels_libraries/libraries/

Плагин требует webman-framework>=1.2.0

Установка

composer require webman/push

Клиентская часть (javascript)

Подключение клиентской части на javascript

<script src="/plugin/webman/push/push.js"> </script>

Использование клиентской части (общедоступный канал)

// Установление соединения
var connection = new Push({
    url: 'ws://127.0.0.1:3131', // адрес веб-сокета
    app_key: '<ключ_приложения, получаемый из config/plugin/webman/push/app.php>',
    auth: '/plugin/webman/push/auth' // аутентификация подписки (только для частных каналов)
});
// Предположим, что идентификатор пользователя (uid) равен 1
var uid = 1;
// Браузер прослушивает сообщения канала user-1, то есть сообщения пользователя с uid=1
var user_channel = connection.subscribe('user-' + uid);

// При поступлении сообщения события в канал user-1
user_channel.on('message', function(data) {
    // в data содержится содержание сообщения
    console.log(data);
});
// При поступлении сообщения события в канал user-1 friendApply
user_channel.on('friendApply', function (data) {
    // в data содержатся сведения о запросе на добавление в друзья
    console.log(data);
});

// Предполагаем, что ID группы равен 2
var group_id = 2;
// Браузер прослушивает сообщения канала group-2, то есть сообщения группы 2
var group_channel = connection.subscribe('group-' + group_id);
// При поступлении сообщения события в канал group-2
group_channel.on('message', function(data) {
    // в data содержится содержание сообщения
    console.log(data);
});

Примечание
В приведенном выше примере подписка реализуется с помощью subscribe, message friendApply - это события на канале. Каналы и события - произвольные строки, не требующие предварительной настройки на сервере.

Серверная часть для передачи данных (PHP)

use Webman\Push\Api;
$api = new Api(
    // в webman можно прямо использовать config для получения настроек; в другом окружении необходимо вручную указать соответствующую конфигурацию
    'http://127.0.0.1:3232',
    config('plugin.webman.push.app.app_key'),
    config('plugin.webman.push.app.app_secret')
);
// Отправить сообщение события message всем клиентам, подписанным на канал user-1
$api->trigger('user-1', 'message', [
    'from_uid' => 2,
    'content'  => 'Привет, это содержание сообщения'
]);

Частные каналы

В рассмотренных выше примерах любой пользователь может подписаться на Push.js для приема информации, но это небезопасно, если информация является конфиденциальной.

webman/push поддерживает подписку на частные каналы, которые начинаются с private-. Например:

var connection = new Push({
    url: 'ws://127.0.0.1:3131', // адрес веб-сокета
    app_key: '<ключ_приложения>',
    auth: '/plugin/webman/push/auth' // аутентификация подписки (только для частных каналов)
});

// Предположим, что идентификатор пользователя (uid) равен 1
var uid = 1;
// Браузер прослушивает сообщения частного канала private-user-1
var user_channel = connection.subscribe('private-user-' + uid);

При подписке клиентом на частный канал (канал, начинающийся с private-), браузер отправляет запрос на аутентификацию AJAX (запрос AJAX имеет адрес, указанный в параметре auth при создании нового объекта Push), где разработчик может проверить, имеет ли текущий пользователь право прослушивать этот канал. Это обеспечивает безопасность подписки.

Дополнительную информацию об аутентификации можно найти в config/plugin/webman/push/route.php

Отправка данных с клиента

В приведенных выше примерах клиентская часть подписывается на определенный канал, а серверная часть вызывает API для отправки данных. webman/push также поддерживает прямую отправку данных с клиента.

Обратите внимание
Отправка данных между клиентами поддерживается только для частных каналов (каналы, начинающиеся с private-), и клиент может генерировать только события, начинающиеся с client-.

Пример генерации события отправки с клиента

var user_channel = connection.subscribe('private-user-1');
user_channel.on('client-message', function (data) {
    // 
});
user_channel.trigger('client-message', {form_uid:2, content:"Привет"});

Обратите внимание
Приведенный выше код отправляет данные события client-message всем клиентам, подписанным на private-user-1, за исключением текущего клиента (отправивший клиент не получит данные, которые он сам отправил).

Вебхуки

Вебхуки используются для получения некоторых событий канала.

В настоящее время существуют два основных события:

  • 1) channel_added
    Событие, срабатывающее при переходе канала от отсутствия онлайна к наличию онлайна, или онлайн-событие

  • 2) channel_removed
    Событие, срабатывающее при отключении всех клиентов канала, или офлайн-событие

Примечание
Эти события очень полезны для отслеживания онлайн-статуса пользователей.

Обратите внимание
URL вебхука настраивается в config/plugin/webman/push/app.php.
Код обработки событий вебхука см. в логике в config/plugin/webman/push/route.php
Из-за того, что обновление страницы приводит к временному отключению пользователя, это не должно считаться как отключение, поэтому webman/push будет выполнять задержанное определение, поэтому события онлайн/оффлайн будут иметь задержку 1-3 секунды.

Прокси wss (SSL)

При использовании протокола https нельзя использовать подключение через ws, поэтому необходимо использовать подключение через wss. Для этого можно использовать прокси wss в nginx, аналогично следующей настройке:

```nginx
server {
    # .... здесь опущены другие настройки ...

    location /app/<app_key>
    {
        proxy_pass http://127.0.0.1:3131;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Обратите внимание, в приведенной выше конфигурации <app_key> получается из config/plugin/webman/push/app.php.

После перезапуска nginx для подключения к серверу используется следующий способ:

var connection = new Push({
    url: 'wss://example.com',
    app_key: '<ключ_приложения, получаемый из config/plugin/webman/push/app.php>',
    auth: '/plugin/webman/push/auth' // аутентификация подписки (только для частных каналов)
});

Обратите внимание

  1. Запрос адреса начинается с wss
  2. Порт не указывается
  3. Необходимо использовать подключение с доменом, соответствующим SSL-сертификату

    Инструкция по использованию push-vue.js

  1. Скопируйте файл push-vue.js в каталог проекта, например, src/utils/push-vue.js.

  2. Импортируйте его на странице vue:

<script lang="ts" setup>
import { onMounted } from 'vue';
import { Push } from '../utils/push-vue';

onMounted(() => {
  console.log('Компонент уже смонтирован');

  // Создание экземпляра webman-push

  // Установка соединения
  var connection = new Push({
    url: 'ws://127.0.0.1:3131', // Адрес веб-сокета
    app_key: '<ключ_приложения_для_получения_в_config/plugin/webman/push/app.php>',
    auth: '/plugin/webman/push/auth' // Аутентификация подписки (только для частных каналов)
  });

  // Предположим, что uid пользователя равен 1
  var uid = 1;
  // Браузер прослушивает сообщения канала user-1, то есть сообщения пользователя с uid 1
  var user_channel = connection.subscribe('user-' + uid);

  // Когда в канале user-1 появляется сообщение с событием message
  user_channel.on('message', function (data) {
    // data содержит содержимое сообщения
    console.log(data);
  });
  // Когда в канале user-1 появляется сообщение с событием friendApply
  user_channel.on('friendApply', function (data) {
    // data содержит информацию о запросе на добавление в друзья
    console.log(data);
  });

  // Предположим, что id группы равен 2
  var group_id = 2;
  // Браузер прослушивает сообщения канала group-2, то есть сообщения группы 2
  var group_channel = connection.subscribe('group-' + group_id);
  // Когда в канале group-2 появляется сообщение с событием message
  group_channel.on('message', function (data) {
    // data содержит содержимое сообщения
    console.log(data);
  });
});
</script>

Другие адреса клиентов

webman/push совместим с pusher, адреса для скачивания других клиентов на различных языках (Java, Swift, .NET, Objective-C, Unity, Flutter, Android, IOS, AngularJS и др.):
https://pusher.com/docs/channels/channels_libraries/libraries/