Gestori CloudEvents di Azure Web PubSub per Express

Il servizio Web PubSub di Azure è un servizio gestito da Azure che consente agli sviluppatori di creare facilmente applicazioni Web con funzionalità in tempo reale e modello di pubblicazione-sottoscrizione. Qualsiasi scenario che richiede la messaggistica di pubblicazione-sottoscrizione in tempo reale tra server e client o tra i client può usare il servizio Web PubSub di Azure. Le funzionalità tradizionali in tempo reale che spesso richiedono il polling dal server o l'invio di richieste HTTP possono usare anche il servizio PubSub Web di Azure.

Quando una connessione WebSocket si connette, il servizio Web PubSub trasforma il ciclo di vita della connessione e i messaggi in eventi in formato CloudEvents. Questa libreria fornisce un middleware rapido per gestire gli eventi che rappresentano il ciclo di vita e i messaggi della connessione WebSocket, come illustrato nel diagramma seguente:

Cloudevents

I dettagli sui termini utilizzati qui sono descritti nella sezione Concetti Chiave .

Codice sorgente | Pacchetto (NPM) | Documentazione di riferimento sulle API | Documentazione del prodotto | Esempi

Come iniziare

Ambienti attualmente supportati

Prerequisiti

1. Installare il @azure/web-pubsub-express pacchetto

npm install @azure/web-pubsub-express

2. Creare un WebPubSubEventHandler

import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat");

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Concetti chiave

Connessione

Una connessione, nota anche come client o connessione client, rappresenta una singola connessione WebSocket collegata al servizio Web PubSub. Quando è connesso con successo, un ID di connessione unico viene assegnato a questa connessione dal servizio Web PubSub.

Hub

Un hub è un concetto logico per un set di connessioni client. Di solito usi un hub per uno scopo, ad esempio un hub chat o un hub di notifiche. Quando viene creata una connessione client, si connette a un hub e, durante la sua durata, appartiene a tale hub. Diverse applicazioni possono condividere un servizio Web PubSub di Azure usando nomi di hub diversi.

Gruppo

Un gruppo è un subset di connessioni all'hub. È possibile aggiungere una connessione client a un gruppo o rimuovere la connessione client dal gruppo in qualsiasi momento. Ad esempio, quando un client si unisce a una chat room o quando un client lascia la chat room, questa chat room può essere considerata un gruppo. Un client può partecipare a più gruppi e un gruppo può contenere più client.

User

Le connessioni a Web PubSub possono appartenere a un utente. Un utente potrebbe avere più connessioni, ad esempio quando un singolo utente è connesso tra più dispositivi o più schede del browser.

Eventi client

Gli eventi vengono creati durante il ciclo di vita di una connessione con il cliente. Ad esempio, una semplice connessione client WebSocket crea un connect evento quando tenta di connettersi al servizio, un connected evento quando si connette con successo al servizio, un message evento quando invia messaggi al servizio e un disconnected evento quando si disconnette dal servizio.

Gestore eventi

Event handler contiene la logica per gestire gli eventi client. Il gestore di eventi deve essere registrato e configurato nel servizio tramite il portale o interfaccia della riga di comando di Azure in anticipo. Il luogo dove ospitare la logica del gestore di eventi è generalmente considerato lato server.

Examples

Gestire la connect richiesta e assegnare <userId>

import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", {
  handleConnect: (req, res) => {
    // auth the connection and set the userId of the connection
    res.success({
      userId: "<userId>",
    });
  },
  allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"],
});

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Gestisci la connect richiesta e rifiuta la connessione se l'autenticazione non funziona

import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", {
  handleConnect: (req, res) => {
    // auth the connection and reject the connection if auth failed
    res.fail(401, "Unauthorized");
    // the following method is also a valid approach
    // res.failWith({ code: 401, detail: "Unauthorized" });
  },
  allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"],
});

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Gestisci la connected richiesta

import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", {
  onConnected: (connectedRequest) => {
    // Your onConnected logic goes here
  },
  allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"],
});

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Gestisci la onGroupJoined richiesta

import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", {
  onGroupJoined: (groupJoinedRequest) => {
    console.log(
      `Connection ${groupJoinedRequest.context.connectionId} joined group ${groupJoinedRequest.group}`,
    );
  },
  allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"],
});

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Gestisci la onGroupLeft richiesta

import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", {
  onGroupLeft: (groupLeftRequest) => {
    console.log(
      `Connection ${groupLeftRequest.context.connectionId} left group ${groupLeftRequest.group}`,
    );
  },
  allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"],
});

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Gestisci la onDisconnected richiesta

import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", {
  onDisconnected: (disconnectedRequest) => {
    // Your onDisconnected logic goes here
  },
  allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"],
});

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Gestire la connect richiesta per mqtt e assign <userId> e <mqtt> proprietà

import { WebPubSubEventHandler, MqttConnectRequest } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", {
  handleConnect: (req, res) => {
    if (req.context.clientProtocol === "mqtt") {
      // return mqtt response when request is of MQTT kind
      // get connect request as mqtt request and print it
      const mqttRequest = req as MqttConnectRequest;
      console.log(mqttRequest);

      // auth the connection and return mqtt response
      res.success({
        userId: "user1",
        mqtt: { userProperties: [{ name: "a", value: "b" }] },
      });
    } else {
      res.success({
        userId: "user1",
      });
    }
  },
  allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"],
});

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Gestisci la connect richiesta di mqtt e rifiuta la connessione se l'autenticazione non funziona

import { WebPubSubEventHandler, MqttConnectRequest } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", {
  handleConnect: (req, res) => {
    // auth the connection and reject the connection if auth failed
    if (req.context.clientProtocol === "mqtt") {
      // return mqtt error response when request is of MQTT kind
      // get connect request as mqtt request and print it
      const mqttRequest = req as MqttConnectRequest;
      console.log(mqttRequest);

      // auth the connection and return mqtt failure response
      res.fail(401, "Not Authorized");

      // Or use below method for more fine-grained control over the MQTT return code
      // res.failWith({ mqtt: { code: MqttV500ConnectReasonCode.NotAuthorized } });
    } else res.success();
  },
  allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"],
});

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Gestire la onDisconnected richiesta per mqtt

import { WebPubSubEventHandler, MqttDisconnectedRequest } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", {
  onDisconnected: (disconnectedRequest) => {
    if (disconnectedRequest.context.clientProtocol === "mqtt") {
      // get disconnect request as mqtt request and print it
      const mqttRequest = disconnectedRequest as MqttDisconnectedRequest;
      console.log(mqttRequest.mqtt);
      // Your onDisconnected logic goes here
    } else {
      console.log(disconnectedRequest);
      // Your onDisconnected logic goes here
    }
  },
  allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"],
});

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Consenti solo i punti finali specificati

import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", {
  allowedEndpoints: [
    "https://<yourAllowedService1>.webpubsub.azure.com",
    "https://<yourAllowedService2>.webpubsub.azure.com",
  ],
});

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Impostare il percorso del gestore eventi personalizzato

import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", {
  path: "/customPath1",
});

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  // Azure WebPubSub Upstream ready at http://localhost:3000/customPath1
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Impostare e leggere lo stato della connessione

import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
import express from "express";

const handler = new WebPubSubEventHandler("chat", {
  handleConnect(req, res) {
    // You can set the state for the connection, it lasts throughout the lifetime of the connection
    res.setState("calledTime", 1);
    res.success();
  },
  handleUserEvent(req, res) {
    const calledTime = req.context.states.calledTime++;
    console.log(calledTime);
    // You can also set the state here
    res.setState("calledTime", calledTime);
    res.success();
  },
});

const app = express();

app.use(handler.getMiddleware());

app.listen(3000, () =>
  console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
);

Troubleshooting

Abilitare i log

L'abilitazione della registrazione può aiutare a individuare informazioni utili sugli errori. Per visualizzare un log di richieste e risposte HTTP, impostare la variabile di ambiente AZURE_LOG_LEVEL su info.

export AZURE_LOG_LEVEL=verbose

In alternativa, la registrazione può essere abilitata in tempo reale chiamando setLogLevel nel @azure/logger:

import { setLogLevel } from "@azure/logger";

setLogLevel("info");

Per istruzioni più dettagliate su come abilitare i log, è possibile esaminare la documentazione del pacchetto @azure/logger.

Tracciamento in tempo reale

Usare Live Trace dal portale del servizio Web PubSub per visualizzare il traffico live.

Passaggi successivi

Dai un'occhiata alla directory samples per esempi dettagliati su come usare questa libreria.

Contributing

Se desideri contribuire a questa libreria, leggi la guida contributi per saperne di più su come costruire e testare il codice.