Compartilhar via


Extensão CloudEvents para o manipulador de eventos do Azure Web PubSub com protocolo HTTP

O serviço Web PubSub fornece eventos de cliente para o webhook upstream usando a Associação de protocolo HTTP CloudEvents.

Os dados enviados do serviço Web PubSub para o servidor estão sempre no formato binary do CloudEvents.

Validação de Webhook

A validação do Webhook segue o CloudEvents. A solicitação sempre contém WebHook-Request-Origin: xxx.webpubsub.azure.com no cabeçalho.

Se e somente se o destino de entrega permitir a entrega dos eventos, ele DEVERÁ responder à solicitação incluindo o cabeçalho WebHook-Allowed-Origin, por exemplo:

WebHook-Allowed-Origin: *

Ou:

WebHook-Allowed-Origin: xxx.webpubsub.azure.com

Por enquanto, WebHook-Request-Rate e WebHook-Request-Callback não têm suporte.

Extensão de atributo CloudEvents da Web PubSub

Também foi observado que a especificação HTTP agora está seguindo um padrão semelhante, não sugerindo mais que os cabeçalhos HTTP de extensão tenham o prefixo X-.

Essa extensão define os atributos usados pelo Web PubSub para cada evento que produz.

Atributos

Nome Tipo Descrição Exemplo
userId string O usuário com a conexão autenticada
hub string O hub ao qual a conexão pertence
connectionId string O connectionId é único para a conexão do cliente
eventName string O nome do evento sem prefixo
subprotocol string O subprotocolo que o cliente está usando, se houver
connectionState string Define o estado da conexão. Você pode usar o mesmo cabeçalho de resposta para redefinir o valor do estado. Não é permitido usar vários cabeçalhos connectionState. Codifique o valor da cadeia de caracteres em base64 se ele contiver caracteres complexos, por exemplo, use base64(jsonString) para transmitir um objeto complexo usando esse atributo.
signature string A assinatura do webhook de upstream para validar se a solicitação de entrada é da origem esperada. O serviço calcula o valor usando a chave de acesso primária e secundária como a chave HMAC: Hex_encoded(HMAC_SHA256(accessKey, connectionId)). O upstream deve verificar se a solicitação é válida antes de processá-la.

Eventos

Há dois tipos de eventos. Um é o evento de bloqueio, cuja resposta é aguardada pelo serviço para continuar. Outro é o evento de desbloqueio para que o serviço não espere a resposta de tal evento antes de processar a próxima mensagem.

Evento connect do sistema

  • ce-type: azure.webpubsub.sys.connect
  • Content-Type: application/json

Formato de solicitação:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.sys.connect
ce-source: /hubs/{hub}/client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub}
ce-eventName: connect

{
    "claims": {},
    "query": {},
    "headers": {},
    "subprotocols": [],
    "clientCertificates": [
        {
            "thumbprint": "ABC"
        }
    ]
}

Formato de resposta de êxito:

  • Cabeçalho ce-connectionState: se esse cabeçalho existir, o estado dessa conexão será atualizado para o valor do cabeçalho. Somente os eventos de bloqueio podem atualizar o estado da conexão. O exemplo abaixo usa a cadeia de caracteres JSON codificada em Base64 para armazenar o estado complexo da conexão.

  • Código de status:

    • 204: êxito, sem conteúdo.
    • 200: êxito, o conteúdo DEVE ser um formato JSON, com as seguintes propriedades permitidas:
      • subprotocols

        O evento connect encaminha as informações de subprotocolo e de autenticação para upstream do cliente. O Serviço Web PubSub usa o código de status para determinar se a solicitação será atualizada para o protocolo WebSocket.

        Se a solicitação contiver a propriedade subprotocols, o servidor deverá retornar um subprotocolo com suporte. Se o servidor não quiser usar nenhum subprotocolo, ele não deve enviar a propriedade subprotocol em resposta. O envio de um cabeçalho em branco é inválido.

      • userId: {auth-ed user ID}

        Como o serviço permite conexões anônimas, é responsabilidade do evento connect informar ao serviço a ID de usuário da conexão do cliente. O serviço lê a ID de usuário do conteúdo de resposta userId, se existir. A conexão será interrompida se a ID de usuário não puder ser lida das declarações de solicitação nem do conteúdo de resposta do evento connect.

      • groups: {groups to join}

        A propriedade fornece uma maneira conveniente para o usuário adicionar essa conexão a um ou vários grupos. Dessa forma, não há necessidade de ter outra chamada para adicionar essa conexão a algum grupo.

      • roles: {roles the client has}

        A propriedade fornece uma maneira para o Webhook upstream autorizar o cliente. Há funções diferentes para conceder permissões iniciais para clientes WebSocket do PubSub. Detalhes sobre as permissões são descritos em Permissões de cliente.

HTTP/1.1 200 OK
ce-connectionState: eyJrZXkiOiJhIn0=

{
    "groups": [],
    "userId": "",
    "roles": [],
    "subprotocol": ""
}

Formato da resposta de erro:

  • 4xx: erro, a resposta do upstream será retornada como a resposta para a solicitação do cliente.
HTTP/1.1 401 Unauthorized

Evento connected do sistema

O serviço chama o upstream quando o cliente conclui o handshake do WebSocket e é conectado com êxito.

  • ce-type: azure.webpubsub.sys.connected
  • Content-Type: application/json
  • ce-connectionState: eyJrZXkiOiJhIn0=

O corpo da solicitação é um JSON vazio.

Formato de solicitação:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.sys.connected
ce-source: /hubs/{hub}/client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub}
ce-eventName: connected
ce-subprotocol: abc
ce-connectionState: eyJrZXkiOiJhIn0=

{}

Formato da resposta:

2xx: resposta de êxito.

connected é um evento assíncrono; quando o código de status de resposta não é bem-sucedido, o serviço registra um erro.

HTTP/1.1 200 OK

Evento disconnected do sistema

O evento disconnected é sempre disparado quando a solicitação do cliente é concluída, se o evento connect retorna o código de status 2xx.

  • ce-type: azure.webpubsub.sys.disconnected
  • Content-Type: application/json

Formato de solicitação:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.sys.disconnected
ce-source: /hubs/{hub}/client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub}
ce-eventName: disconnected
ce-subprotocol: abc
ce-connectionState: eyJrZXkiOiJhIn0=

{
    "reason": "{Reason}"
}

  • reason

    O reason descreve o motivo pelo qual o cliente se desconecta.

Formato da resposta:

2xx: resposta de êxito.

disconnected é um evento assíncrono; quando o código de status de resposta não é bem-sucedido, o serviço registra um erro.

HTTP/1.1 200 OK

Evento de usuário message para clientes WebSocket simples

O serviço invoca o manipulador de eventos upstream para cada quadro de mensagem WebSocket.

  • ce-type: azure.webpubsub.user.message
  • Content-Type: application/octet-stream para quadro binário; text/plain para quadro de texto;

UserPayload é o que o cliente envia.

Formato de solicitação:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/octet-stream | text/plain | application/json
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.message
ce-source: /hubs/{hub}/client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub}
ce-eventName: message
ce-connectionState: eyJrZXkiOiJhIn0=

UserPayload

Formato de resposta de êxito

  • Código de status
    • 204: êxito, sem conteúdo.
    • 200: êxito, o formato de UserResponsePayload depende de Content-Type da resposta.
  • Content-Type: application/octet-stream para quadro binário; text/plain para quadro de texto;
  • Cabeçalho Content-Type: application/octet-stream para o quadro binário; text/plain para o quadro de texto;
  • Cabeçalho ce-connectionState: se esse cabeçalho existir, o estado dessa conexão será atualizado para o valor do cabeçalho. Somente os eventos de bloqueio podem atualizar o estado da conexão. O exemplo abaixo usa a cadeia de caracteres JSON codificada em Base64 para armazenar o estado complexo da conexão.

Quando Content-Type for application/octet-stream, o serviço envia UserResponsePayload para o cliente usando o quadro WebSocket binary. Quando Content-Type for text/plain, o serviço envia UserResponsePayload para o cliente usando o quadro WebSocket text.

HTTP/1.1 200 OK
Content-Type: application/octet-stream (for binary frame) or text/plain (for text frame)
Content-Length: nnnn
ce-connectionState: eyJrZXkiOiJhIn0=

UserResponsePayload

Formato da resposta de erro

Quando o código de status não é êxito, ele é considerado uma resposta de erro. A conexão será interrompida se o código de status de resposta message não for de êxito.

Evento personalizado do usuário {custom_event} para clientes PubSub WebSocket

O serviço chama o webhook do manipulador de eventos para cada mensagem de evento personalizado válida.

Caso 1: enviar evento com dados de texto:

{
    "type": "event",
    "event": "<event_name>",
    "dataType" : "text",
    "data": "text data"
}

O que o manipulador de eventos de upstream recebe como abaixo, o Content-Type para a solicitação HTTP do CloudEvents é text/plain para dataType=text

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: text/plain
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>
ce-subprotocol: json.webpubsub.azure.v1
ce-connectionState: eyJrZXkiOiJhIn0=

text data

Caso 2: enviar evento com dados JSON:

{
    "type": "event",
    "event": "<event_name>",
    "dataType" : "json",
    "data": {
        "hello": "world"
    },
}

O que o manipulador de eventos de upstream recebe como abaixo, o Content-Type para a solicitação HTTP do CloudEvents é application/json para dataType=json

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/json
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>
ce-subprotocol: json.webpubsub.azure.v1
ce-connectionState: eyJrZXkiOiJhIn0=

{
    "hello": "world"
}

Caso 3: enviar evento com dados binários:

{
    "type": "event",
    "event": "<event_name>",
    "dataType" : "binary",
    "data": "aGVsbG8gd29ybGQ=" // base64 encoded binary
}

O que o manipulador de eventos de upstream recebe como abaixo, o Content-Type para a solicitação HTTP do CloudEvents é application/octet-stream para dataType=binary

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/octet-stream
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>
ce-subprotocol: json.webpubsub.azure.v1

<binary data>

Formato de resposta de êxito

HTTP/1.1 200 OK
Content-Type: application/octet-stream | text/plain | application/json
Content-Length: nnnn

UserResponsePayload
  • Código de status
    • 204: êxito, sem conteúdo.
    • 200: êxito, o envio de dados para o cliente PubSub WebSocket depende do Content-Type;
  • Cabeçalho ce-connectionState: se esse cabeçalho existir, o estado dessa conexão será atualizado para o valor do cabeçalho. Somente os eventos de bloqueio podem atualizar o estado da conexão. O exemplo abaixo usa a cadeia de caracteres JSON codificada em Base64 para armazenar o estado complexo da conexão.
  • Quando o cabeçalho Content-Type for application/octet-stream, o serviço enviará UserResponsePayload de volta ao cliente usando dataType como binary com a carga codificada em Base64. Um exemplo de resposta:
    {
        "type": "message",
        "from": "server",
        "dataType": "binary",
        "data" : "aGVsbG8gd29ybGQ="
    }
    
  • Quando Content-Type for text/plain, o serviço envia UserResponsePayload ao cliente usando dataType como text com a cadeia de caracteres do conteúdo.
  • Quando Content-Type for application/json, o serviço envia UserResponsePayload ao cliente usando dataType=json com o token de valor data como o corpo conteúdo de resposta.

Formato da resposta de erro

Quando o código de status não é êxito, ele é considerado uma resposta de erro. A conexão será interrompida se o código de status de resposta {custom_event} não for de êxito.

Próximas etapas

Use estes recursos para começar a criar seu aplicativo: