Pengendali CloudEvents Azure Web PubSub untuk Express

Layanan Azure Web PubSub adalah layanan terkelola Azure yang membantu pengembang dengan mudah membangun aplikasi web dengan fitur real-time dan pola terbitkan-berlangganan. Skenario apa pun yang memerlukan pesan terbitkan-berlangganan real time antara server dan klien atau di antara klien dapat menggunakan layanan Azure Web PubSub. Fitur real-time tradisional yang sering memerlukan polling dari server atau mengirimkan permintaan HTTP juga dapat menggunakan layanan Azure Web PubSub.

Saat koneksi WebSocket tersambung, layanan Web PubSub mengubah siklus hidup koneksi dan pesan menjadi peristiwa dalam format CloudEvents. Pustaka ini menyediakan middleware ekspres untuk menangani peristiwa yang mewakili siklus hidup dan pesan koneksi WebSocket, seperti yang ditunjukkan pada diagram di bawah ini:

cloudevents

Detail tentang istilah yang digunakan di sini dijelaskan di bagian Konsep utama .

Kode sumber | Paket (NPM) | Dokumentasi | referensi APIDokumentasi | produkSampel

Memulai Langkah Pertama

Lingkungan yang didukung saat ini

Prasyarat

  • Sebuah langganan Azure.
  • Titik akhir Azure Web PubSub yang sudah ada.

1. Instal @azure/web-pubsub-express paket

npm install @azure/web-pubsub-express

2. Buat 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}`),
);

Konsep Utama

Connection

Koneksi, juga dikenal sebagai koneksi klien atau klien, mewakili koneksi WebSocket individu yang terhubung ke layanan Web PubSub. Saat berhasil terhubung, ID koneksi unik ditetapkan ke koneksi ini oleh layanan Web PubSub.

Pusat

Hub adalah konsep logis untuk sekumpulan koneksi klien. Biasanya Anda menggunakan satu hub untuk satu tujuan, misalnya, hub obrolan, atau hub notifikasi. Saat koneksi klien dibuat, koneksi terhubung ke hub, dan selama masa pakainya, koneksi tersebut milik hub tersebut. Aplikasi yang berbeda dapat berbagi satu layanan Azure Web PubSub dengan menggunakan nama hub yang berbeda.

Kelompok

Grup adalah subset koneksi ke hub. Anda dapat menambahkan koneksi klien ke grup, atau menghapus koneksi klien dari grup, kapan saja Anda mau. Misalnya, ketika klien bergabung dengan ruang obrolan, atau ketika klien meninggalkan ruang obrolan, ruang obrolan ini dapat dianggap sebagai grup. Klien dapat bergabung dengan beberapa grup, dan grup dapat berisi beberapa klien.

User

Koneksi ke Web PubSub bisa menjadi milik satu pengguna. Pengguna mungkin memiliki beberapa koneksi, misalnya saat satu pengguna terhubung di beberapa perangkat atau beberapa tab browser.

Peristiwa Klien

Peristiwa dibuat selama siklus hidup koneksi klien. Misalnya, koneksi klien WebSocket sederhana membuat connect peristiwa saat mencoba terhubung ke layanan, connected peristiwa saat berhasil terhubung ke layanan, peristiwa saat mengirim pesan ke layanan, message dan disconnected peristiwa saat terputus dari layanan.

Pengendali Acara

Penanganan peristiwa berisi logika untuk menangani peristiwa klien. Penanganan peristiwa perlu didaftarkan dan dikonfigurasi dalam layanan melalui portal atau Azure CLI sebelumnya. Tempat untuk menghosting logika penanganan peristiwa umumnya dianggap sebagai sisi server.

Contoh

Tangani permintaan connect dan tetapkan <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}`),
);

Tangani connect permintaan dan tolak koneksi jika autentikasi gagal

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}`),
);

Menangani connected permintaan

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}`),
);

Menangani onGroupJoined permintaan

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}`),
);

Menangani onGroupLeft permintaan

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}`),
);

Menangani onDisconnected permintaan

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}`),
);

Menangani connect permintaan untuk mqtt dan menetapkan <userId> dan <mqtt> properti

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}`),
);

Tangani connect permintaan untuk mqtt dan tolak koneksi jika otentikasi gagal

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}`),
);

Menangani onDisconnected permintaan for 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}`),
);

Hanya izinkan titik akhir yang ditentukan

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}`),
);

Mengatur jalur penanganan aktivitas kustom

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}`),
);

Mengatur dan membaca status koneksi

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

Aktifkan log

Mengaktifkan pengelogan dapat membantu menemukan informasi yang berguna tentang kegagalan. Untuk melihat log permintaan dan respons HTTP, atur variabel lingkungan AZURE_LOG_LEVEL ke info.

export AZURE_LOG_LEVEL=verbose

Atau, pengelogan dapat diaktifkan saat runtime dengan memanggil setLogLevel di @azure/logger:

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

setLogLevel("info");

Untuk instruksi lebih rinci tentang cara mengaktifkan log, Anda dapat melihat dokumen paket @azure/logger.

Pelacakan Langsung

Gunakan Live Trace dari portal layanan Web PubSub untuk melihat lalu lintas langsung.

Langkah berikutnya

Silakan lihat direktori samples untuk contoh terperinci tentang cara menggunakan library ini.

Contributing

Jika Anda ingin berkontribusi ke library ini, silakan baca panduan contributor untuk mempelajari lebih lanjut cara membuat dan menguji kode.