Протоколы клиента WebSocket для Azure Web PubSub

Клиенты подключаются к Azure Web PubSub с помощью стандартного протокола WebSocket .

Конечные точки служб

Служба Web PubSub предоставляет два типа конечных точек для подключения клиентов:

  • /client/hubs/{hub}
  • /client/?hub={hub}

{hub} — обязательный параметр, который выступает в качестве изоляции для различных приложений. Параметр можно задать либо в пути, либо в запросе.

Авторизация

Клиенты подключаются к службе с помощью веб-маркера JSON (JWT). Маркер может находиться в строке запроса, как /client/?hub={hub}&access_token={token}или в заголовкеAuthorization.Authorization: Bearer {token}

Ниже приведен общий рабочий процесс авторизации:

  1. Клиент ведет переговоры с сервером приложений. Сервер приложений содержит ПО промежуточного слоя авторизации, которое обрабатывает запрос клиента и подписывает JWT для клиента для подключения к службе.
  2. Сервер приложений возвращает JWT и URL-адрес службы клиенту.
  3. Клиент пытается подключиться к службе Web PubSub с помощью URL-адреса и JWT, возвращенного сервером приложений.

Поддерживаемые утверждения

При генерации токена доступа можно также настроить параметры подключения клиента, указав специальные утверждения в JWT.

Описание Тип утверждения Значение утверждения Заметки
Элемент userId для подключения клиента sub идентификатор пользователя Допускается только одно sub утверждение.
Время существования маркера exp время окончания срока действия Утверждение exp (время окончания срока действия) определяет время, после которого токен НИКАК НЕ должен приниматься для обработки.
Разрешения, которые изначально имеет подключение клиента role значение роли, определенное в разрешениях Укажите несколько утверждений, если у клиента есть несколько role разрешений.
Начальные группы, присоединенные к клиентскому подключению после подключения к Azure Web PubSub webpubsub.group группа, к которой можно присоединиться Укажите несколько webpubsub.group утверждений, если клиент присоединяется к нескольким группам.

Можно также добавить пользовательские утверждения в маркер доступа, и эти значения сохраняются в качестве claims свойства в тексте запроса на подключение.

Пакеты SDK сервера предоставляют API для создания токена доступа для клиентов.

Простой клиент WebSocket

Простой клиент WebSocket, как следует из названия, представляет собой простое соединение WebSocket. Он также может иметь собственный подпротокол.

Например, в JavaScript можно создать простой клиент WebSocket с помощью следующего кода:

// simple WebSocket client1
var client1 = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1');

// simple WebSocket client2 with some custom subprotocol
var client2 = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'custom.subprotocol')

Простой клиент WebSocket имеет два режима: sendEvent и sendToGroup. Режим определяется после установки подключения и не может быть изменен позже.

sendEvent — это режим по умолчанию для простого клиента WebSocket. В sendEvent режиме каждый кадр WebSocket, отправляемый клиентом, считается событием message . Пользователи могут настроить обработчики событий или прослушиватели событий для обработки этих message событий.

// Every data frame is considered as a `message` event
var client3 = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1');

// Or explicitly set the mode
var client4 = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1?webpubsub_mode=sendEvent');

В sendToGroup режиме каждый кадр WebSocket, отправляемый клиентом, считается сообщением, которое будет опубликовано в определенной группе. group является обязательным параметром запроса в этом режиме, и допускается только одно значение. Подключение также должно иметь соответствующие разрешения для отправки сообщений в целевую группу. Оба webpubsub.sendToGroup.<group> и webpubsub.sendToGroup роли работают для него.

Например, в JavaScript можно создать простой клиент WebSocket с помощью следующего кода в sendToGroup режиме с group=group1.

var client5 = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1?webpubsub_mode=sendToGroup&group=group1');

Клиент PubSub WebSocket

Клиент PubSub WebSocket — это клиент WebSocket, использующий подпротоколы, определенные службой Azure Web PubSub:

  • json.webpubsub.azure.v1
  • protobuf.webpubsub.azure.v1

С помощью подпротокола, поддерживаемого службой, клиент PubSub WebSocketможет напрямую публиковать сообщения в группах при наличии разрешений.

Подпротокол json.webpubsub.azure.v1

Подробные сведения о подпротоколе JSON см. здесь.

Создание клиента PubSub WebSocket

var pubsubClient = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'json.webpubsub.azure.v1');

Присоединитесь напрямую к группе клиента

let ackId = 0;
pubsubClient.send(
    JSON.stringify({
        type: 'joinGroup',
        group: 'group1',
        ackId: ++ackId
    }));

Отправка сообщений в группу из клиента напрямую

let ackId = 0;
pubsubClient.send(
    JSON.stringify({
        type: 'sendToGroup',
        group: 'group1',
        ackId: ++ackId,
        dataType: "json",
        data: {
            "hello": "world"
        }
    }));

Подпротокол protobuf.webpubsub.azure.v1

Буферы протокола (protobuf) — это нейтральный на языке, нейтральный от платформы, двоичный протокол, упрощающий отправку двоичных данных. Protobuf предоставляет средства для создания клиентов для многих языков, таких как Java, Python, Objective-C, C#и C++. Дополнительные сведения о protobuf.

Например, в JavaScript можно создать клиент PubSub WebSocket с подпротоколом protobuf с помощью следующего кода:

// PubSub WebSocket client
var pubsub = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'protobuf.webpubsub.azure.v1');

Подробные сведения о подпротоколе protobuf можно найти здесь.

Ответ AckId и Ack

Клиент PubSub WebSocket поддерживает ackId свойство для сообщений joinGroup, leaveGroup, sendToGroup и event. При использовании ackId можно получить подтверждение об успешной обработке запроса. Вы можете исключить ackId сценарии пожара и забыть. В статье описаны различия в поведении между указанием ackId или нет.

Поведение при отсутствии ackId указанного значения

Если ackId не указан, выполняется "fire-and-forget". Даже если возникают ошибки при обработке сообщений, нет возможности получить уведомление.

Поведение, когда ackId указано

Идемпотентная публикация

ackId — это номер uint64 и должен быть уникальным в клиенте с тем же идентификатором подключения. Служба Web PubSub записывает ackId, а сообщения с тем же ackId рассматриваются как одинаковые. Служба отказывается передавать одно и то же сообщение через брокера более одного раза, что полезно при повторных попытках, чтобы избежать дублирования сообщений. Например, если клиент отправляет сообщение с ackId=5 и не получает отклик в виде подтверждения (ack) с ackId=5, то клиент повторяет попытку и снова отправляет то же сообщение. В некоторых случаях сообщение уже обработано брокером, и подтверждение (ack) теряется по какой-то причине. Служба отклоняет повторные попытки и отправляет подтверждение с причиной Duplicate.

Ответ Ack

Служба Web PubSub отправляет ответ ack для каждого запроса с ackId.

Формат

{
    "type": "ack",
    "ackId": 1, // The ack id for the request to ack
    "success": false, // true or false
    "error": {
        "name": "Forbidden|InternalServerError|Duplicate",
        "message": "<error_detail>"
    }
}
  • Объект ackId связывает запрос.

  • success — это логическое значение и указывает, успешно ли запрос обрабатывается службой. Если false, клиенты должны проверить error.

  • error существует только в том случае, если successfalse, и клиенты должны использовать другую логику для разных name. Предположим, что в будущем может быть больше типов name .

    • Forbidden: у клиента нет разрешения на запрос. Клиенту необходимо добавить соответствующие роли.
    • InternalServerError: в службе произошла некоторая внутренняя ошибка. Требуется повторная попытка.
    • Duplicate: сообщение с тем же ackId уже обработано службой.

Разрешения

Как вы, вероятно, заметили в предыдущем описании клиента PubSub WebSocket, клиент может публиковаться на других клиентах только в том случае, если это разрешено . Разрешения клиента можно предоставить при подключении или в течение времени действия подключения.

Роль Разрешение
Не указано Клиент может отправлять запросы на события.
webpubsub.joinLeaveGroup Клиент может присоединиться или оставить любую группу.
webpubsub.sendToGroup Клиент может публиковать сообщения в любой группе.
webpubsub.joinLeaveGroup.<group> Клиент может присоединиться или оставить группу <group>.
webpubsub.sendToGroup.<group> Клиент может публиковать сообщения в группе <group>.
webpubsub.joinLeaveGroups.<pattern> Клиент может вступить в любую группу или покинуть её, имя которой совпадает с <pattern> (см. шаблоны ролей групп с использованием подстановочных знаков).
webpubsub.sendToGroups.<pattern> Клиент может публиковать сообщения в любой группе, имя которой совпадает <pattern> (см. шаблоны ролей групп с подстановочными знаками).

Разрешение клиента можно предоставить несколькими способами:

1. Назначение роли клиенту при создании токена доступа

Клиент может подключиться к службе с помощью JWT. Полезные данные маркера могут содержать такую информацию, как role клиента. При подписании JWT клиенту вы можете предоставить ему разрешения, присвоив клиенту определенные роли.

Например, давайте подпишем JWT с разрешением на отправку сообщений в group1 и group2.

let token = await serviceClient.getClientAccessToken({
    roles: [ "webpubsub.sendToGroup.group1", "webpubsub.sendToGroup.group2" ]
});

2. Назначение роли клиенту с помощью обработчика connect событий

Роли клиентов также можно задать при connect регистрации обработчика событий, и вышестоящий обработчик событий может вернуть roles клиента в службу Web PubSub при обработке connect событий.

Например, в JavaScript можно настроить handleConnect событие для этого:

let handler = new WebPubSubEventHandler("hub1", {
  handleConnect: (req, res) => {
    // auth the connection and set the userId of the connection
    res.success({
      roles: [ "webpubsub.sendToGroup.group1", "webpubsub.sendToGroup.group2" ]
    });
  },
});

3. Назначьте роль клиенту через REST API или серверные SDK в режиме выполнения

let service = new WebPubSubServiceClient("<your_connection_string>", "test-hub");
await service.grantPermission("<connection_id>", "joinLeaveGroup", { targetName: "group1" });

Замечание

Назначение ролей с подстановочными знаками, таких как webpubsub.sendToGroups.<pattern>, через REST API или серверные SDK пока не поддерживается. Эта функция будет поддерживаться в будущем обновлении.

Дальнейшие действия

Используйте эти ресурсы для начала создания собственного приложения: