Azure Web PubSub CloudEvents 处理快递程序
Azure Web PubSub 服务 是一种由Azure管理的服务,帮助开发者轻松地构建具有实时功能并发布订阅模式的网络应用程序. 任何需要服务器和客户端之间或客户端之间实时发布订阅消息的情景都可以使用Azure Web PubSub服务. 传统的实时功能往往需要服务器投票或提交HTTP请求也可以使用Azure Web PubSub服务.
当一个 WebSocket 连接连接时, Web PubSub 服务将连接寿命周期和信件转换为 cloudEvents 格式的事件。该库提供了一种快速的中间软件,用于处理代表WebSocket连接的生命周期和消息的事件,如下图所示:

此处所用术语的详情如下: 关键概念 节.
源代码 | 软件包( NPM) | API 参考文件 | 产品文档 | 样本
开始
目前得到支持的环境
- 节点.js的LTS版本
- 快递 4.x.x或更高版本
先决条件
- 一个 Azure 订阅。 。 。 .
- 已存在的 Azure Web PubSub 端点 .
1. 安装 @azure/web-pubsub-express 软件包
npm install @azure/web-pubsub-express
2. 创建一个 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}`),
);
关键概念
连接
连接也称为客户端或客户端连接,代表个人WebSocket连接到Web PubSub服务. 成功连接时,由Web PubSub服务为此连接指定了独特的连接ID.
枢纽
中枢是一组客户端连接的逻辑概念. 通常您会为一个目的使用一个中枢,例如聊天中枢,或者通知中枢. 当客户端连接被创建时,它会连接到一个中枢,在其存在期间,它属于那个中枢. 不同的应用程序可以通过使用不同的中枢名称共享一个Azure Web PubSub服务.
组
一组是连接到中枢的子集. 您可以在组中添加客户端连接, 或者随时从组中去除客户端连接 。 例如,当客户端加入聊天室,或者当客户端离开聊天室时,这个聊天室可以被认为是一个组. 一个客户端可以加入多个组,一个组可以包含多个客户端.
用户
连接到 Web PubSub 可以属于一个用户. 一个用户可能拥有多个连接,例如当一个用户通过多个设备或多个浏览器标签连接时.
客户事件
事件是在客户端连接的生命周期内创建的. 例如,一个简单的 WebSocket 客户端连接创建一个 connect 当它试图连接到服务时, a connected 当成功连接到服务时, a message 当它向服务发送消息时的事件和 a disconnected 当它与服务断开时.
事件处理器
事件处理器包含处理客户端事件的逻辑. 事件处理器需要事先通过门户或Azure CLI在服务中注册和配置. 事件处理器逻辑的主机位置一般被认为是服务器侧.
实例
处理 connect 请求和指定 <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}`),
);
处理 connect 如果 auth 失败, 请请求并拒绝连接
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}`),
);
处理 connected 请求
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}`),
);
处理 onGroupJoined 请求
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}`),
);
处理 onGroupLeft 请求
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}`),
);
处理 onDisconnected 请求
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}`),
);
处理 connect 请求 mqtt 并指定 <userId> 财务报告和审定财务报表 <mqtt> 属性
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}`),
);
处理 connect 如果 auth 失败, 请求 mqtt 并拒绝连接
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}`),
);
处理 onDisconnected 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}`),
);
只允许指定终点
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}`),
);
设置自定义事件处理器路径
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}`),
);
设置并读取连接状态
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}`),
);
解决问题
启用日志
允许伐木可能有助于发现有关失败的有用信息。 为了查看 HTTP 请求和回复的日志,设置 AZURE_LOG_LEVEL 环境变量改为 info。 。 。 .
export AZURE_LOG_LEVEL=verbose
也可以在运行时通过呼叫启用日志 setLogLevel 输入 @azure/logger数字 :
import { setLogLevel } from "@azure/logger";
setLogLevel("info");
关于如何启用日志的更详细指示,您可以查看 @ azure/ logger 包文件。 。 。 .
现场追踪
使用 现场追踪 从Web PubSub服务门户查看直播流量.
今后的步骤
请看一下 样本 关于如何使用此库的详细示例的目录.
捐款
如果您想为图书馆捐钱 请读一下 贡献指南 学习如何构建和测试密码.