@azure/web-pubsub-express 1.0.6-alpha.20250224.1 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -46
- package/dist/browser/cloudEventsDispatcher.d.ts +15 -0
- package/dist/browser/cloudEventsDispatcher.d.ts.map +1 -0
- package/dist/browser/cloudEventsDispatcher.js +411 -0
- package/dist/browser/cloudEventsDispatcher.js.map +1 -0
- package/dist/browser/cloudEventsProtocols.d.ts +411 -0
- package/dist/browser/cloudEventsProtocols.d.ts.map +1 -0
- package/dist/browser/cloudEventsProtocols.js +4 -0
- package/dist/browser/cloudEventsProtocols.js.map +1 -0
- package/dist/browser/enum/MqttErrorCodes/mqttDisconnectReasonCode.d.ts +180 -0
- package/dist/browser/enum/MqttErrorCodes/mqttDisconnectReasonCode.d.ts.map +1 -0
- package/dist/browser/enum/MqttErrorCodes/mqttDisconnectReasonCode.js +183 -0
- package/dist/browser/enum/MqttErrorCodes/mqttDisconnectReasonCode.js.map +1 -0
- package/dist/browser/enum/MqttErrorCodes/mqttV311ConnectReturnCode.d.ts +31 -0
- package/dist/browser/enum/MqttErrorCodes/mqttV311ConnectReturnCode.d.ts.map +1 -0
- package/dist/browser/enum/MqttErrorCodes/mqttV311ConnectReturnCode.js +34 -0
- package/dist/browser/enum/MqttErrorCodes/mqttV311ConnectReturnCode.js.map +1 -0
- package/dist/browser/enum/MqttErrorCodes/mqttV500ConnectReasonCode.d.ts +112 -0
- package/dist/browser/enum/MqttErrorCodes/mqttV500ConnectReasonCode.d.ts.map +1 -0
- package/dist/browser/enum/MqttErrorCodes/mqttV500ConnectReasonCode.js +115 -0
- package/dist/browser/enum/MqttErrorCodes/mqttV500ConnectReasonCode.js.map +1 -0
- package/dist/browser/index.d.ts +6 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +8 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/logger.d.ts +7 -0
- package/dist/browser/logger.d.ts.map +1 -0
- package/dist/browser/logger.js +10 -0
- package/dist/browser/logger.js.map +1 -0
- package/dist/browser/package.json +3 -0
- package/dist/browser/utils.d.ts +6 -0
- package/dist/browser/utils.d.ts.map +1 -0
- package/dist/browser/utils.js +53 -0
- package/dist/browser/utils.js.map +1 -0
- package/dist/browser/webPubSubEventHandler.d.ts +46 -0
- package/dist/browser/webPubSubEventHandler.d.ts.map +1 -0
- package/dist/browser/webPubSubEventHandler.js +73 -0
- package/dist/browser/webPubSubEventHandler.js.map +1 -0
- package/dist/commonjs/index.js +14 -880
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/webPubSubEventHandler.d.ts +7 -8
- package/dist/commonjs/webPubSubEventHandler.d.ts.map +1 -1
- package/dist/commonjs/webPubSubEventHandler.js +7 -8
- package/dist/commonjs/webPubSubEventHandler.js.map +1 -1
- package/dist/esm/webPubSubEventHandler.d.ts +7 -8
- package/dist/esm/webPubSubEventHandler.d.ts.map +1 -1
- package/dist/esm/webPubSubEventHandler.js +7 -8
- package/dist/esm/webPubSubEventHandler.js.map +1 -1
- package/dist/react-native/cloudEventsDispatcher.d.ts +15 -0
- package/dist/react-native/cloudEventsDispatcher.d.ts.map +1 -0
- package/dist/react-native/cloudEventsDispatcher.js +411 -0
- package/dist/react-native/cloudEventsDispatcher.js.map +1 -0
- package/dist/react-native/cloudEventsProtocols.d.ts +411 -0
- package/dist/react-native/cloudEventsProtocols.d.ts.map +1 -0
- package/dist/react-native/cloudEventsProtocols.js +4 -0
- package/dist/react-native/cloudEventsProtocols.js.map +1 -0
- package/dist/react-native/enum/MqttErrorCodes/mqttDisconnectReasonCode.d.ts +180 -0
- package/dist/react-native/enum/MqttErrorCodes/mqttDisconnectReasonCode.d.ts.map +1 -0
- package/dist/react-native/enum/MqttErrorCodes/mqttDisconnectReasonCode.js +183 -0
- package/dist/react-native/enum/MqttErrorCodes/mqttDisconnectReasonCode.js.map +1 -0
- package/dist/react-native/enum/MqttErrorCodes/mqttV311ConnectReturnCode.d.ts +31 -0
- package/dist/react-native/enum/MqttErrorCodes/mqttV311ConnectReturnCode.d.ts.map +1 -0
- package/dist/react-native/enum/MqttErrorCodes/mqttV311ConnectReturnCode.js +34 -0
- package/dist/react-native/enum/MqttErrorCodes/mqttV311ConnectReturnCode.js.map +1 -0
- package/dist/react-native/enum/MqttErrorCodes/mqttV500ConnectReasonCode.d.ts +112 -0
- package/dist/react-native/enum/MqttErrorCodes/mqttV500ConnectReasonCode.d.ts.map +1 -0
- package/dist/react-native/enum/MqttErrorCodes/mqttV500ConnectReasonCode.js +115 -0
- package/dist/react-native/enum/MqttErrorCodes/mqttV500ConnectReasonCode.js.map +1 -0
- package/dist/react-native/index.d.ts +6 -0
- package/dist/react-native/index.d.ts.map +1 -0
- package/dist/react-native/index.js +8 -0
- package/dist/react-native/index.js.map +1 -0
- package/dist/react-native/logger.d.ts +7 -0
- package/dist/react-native/logger.d.ts.map +1 -0
- package/dist/react-native/logger.js +10 -0
- package/dist/react-native/logger.js.map +1 -0
- package/dist/react-native/package.json +3 -0
- package/dist/react-native/utils.d.ts +6 -0
- package/dist/react-native/utils.d.ts.map +1 -0
- package/dist/react-native/utils.js +53 -0
- package/dist/react-native/utils.js.map +1 -0
- package/dist/react-native/webPubSubEventHandler.d.ts +46 -0
- package/dist/react-native/webPubSubEventHandler.d.ts.map +1 -0
- package/dist/react-native/webPubSubEventHandler.js +73 -0
- package/dist/react-native/webPubSubEventHandler.js.map +1 -0
- package/package.json +33 -17
package/README.md
CHANGED
|
@@ -34,10 +34,10 @@ npm install @azure/web-pubsub-express
|
|
|
34
34
|
|
|
35
35
|
### 2. Create a `WebPubSubEventHandler`
|
|
36
36
|
|
|
37
|
-
```
|
|
38
|
-
|
|
37
|
+
```ts snippet:ReadmeSampleCreateClient
|
|
38
|
+
import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
|
|
39
|
+
import express from "express";
|
|
39
40
|
|
|
40
|
-
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
41
41
|
const handler = new WebPubSubEventHandler("chat");
|
|
42
42
|
|
|
43
43
|
const app = express();
|
|
@@ -79,10 +79,10 @@ Event handler contains the logic to handle the client events. Event handler need
|
|
|
79
79
|
|
|
80
80
|
### Handle the `connect` request and assign `<userId>`
|
|
81
81
|
|
|
82
|
-
```
|
|
83
|
-
|
|
82
|
+
```ts snippet:ReadmeSampleConnect
|
|
83
|
+
import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
|
|
84
|
+
import express from "express";
|
|
84
85
|
|
|
85
|
-
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
86
86
|
const handler = new WebPubSubEventHandler("chat", {
|
|
87
87
|
handleConnect: (req, res) => {
|
|
88
88
|
// auth the connection and set the userId of the connection
|
|
@@ -104,10 +104,10 @@ app.listen(3000, () =>
|
|
|
104
104
|
|
|
105
105
|
### Handle the `connect` request and reject the connection if auth failed
|
|
106
106
|
|
|
107
|
-
```
|
|
108
|
-
|
|
107
|
+
```ts snippet:ReadmeSampleConnectAndReject
|
|
108
|
+
import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
|
|
109
|
+
import express from "express";
|
|
109
110
|
|
|
110
|
-
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
111
111
|
const handler = new WebPubSubEventHandler("chat", {
|
|
112
112
|
handleConnect: (req, res) => {
|
|
113
113
|
// auth the connection and reject the connection if auth failed
|
|
@@ -129,10 +129,10 @@ app.listen(3000, () =>
|
|
|
129
129
|
|
|
130
130
|
### Handle the `connected` request
|
|
131
131
|
|
|
132
|
-
```
|
|
133
|
-
|
|
132
|
+
```ts snippet:ReadmeSampleConnected
|
|
133
|
+
import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
|
|
134
|
+
import express from "express";
|
|
134
135
|
|
|
135
|
-
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
136
136
|
const handler = new WebPubSubEventHandler("chat", {
|
|
137
137
|
onConnected: (connectedRequest) => {
|
|
138
138
|
// Your onConnected logic goes here
|
|
@@ -151,10 +151,10 @@ app.listen(3000, () =>
|
|
|
151
151
|
|
|
152
152
|
### Handle the `onDisconnected` request
|
|
153
153
|
|
|
154
|
-
```
|
|
155
|
-
|
|
154
|
+
```ts snippet:ReadmeSampleDisconnected
|
|
155
|
+
import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
|
|
156
|
+
import express from "express";
|
|
156
157
|
|
|
157
|
-
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
158
158
|
const handler = new WebPubSubEventHandler("chat", {
|
|
159
159
|
onDisconnected: (disconnectedRequest) => {
|
|
160
160
|
// Your onDisconnected logic goes here
|
|
@@ -173,14 +173,15 @@ app.listen(3000, () =>
|
|
|
173
173
|
|
|
174
174
|
### Handle the `connect` request for mqtt and assign `<userId>` and `<mqtt>` properties
|
|
175
175
|
|
|
176
|
-
```
|
|
177
|
-
|
|
176
|
+
```ts snippet:ReadmeSampleConnectMqtt
|
|
177
|
+
import { WebPubSubEventHandler, MqttConnectRequest } from "@azure/web-pubsub-express";
|
|
178
|
+
import express from "express";
|
|
178
179
|
|
|
179
|
-
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
180
180
|
const handler = new WebPubSubEventHandler("chat", {
|
|
181
181
|
handleConnect: (req, res) => {
|
|
182
|
-
if (req.context.clientProtocol === "mqtt") {
|
|
183
|
-
|
|
182
|
+
if (req.context.clientProtocol === "mqtt") {
|
|
183
|
+
// return mqtt response when request is of MQTT kind
|
|
184
|
+
// get connect request as mqtt request and print it
|
|
184
185
|
const mqttRequest = req as MqttConnectRequest;
|
|
185
186
|
console.log(mqttRequest);
|
|
186
187
|
|
|
@@ -195,7 +196,7 @@ const handler = new WebPubSubEventHandler("chat", {
|
|
|
195
196
|
});
|
|
196
197
|
}
|
|
197
198
|
},
|
|
198
|
-
allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"]
|
|
199
|
+
allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"],
|
|
199
200
|
});
|
|
200
201
|
|
|
201
202
|
const app = express();
|
|
@@ -203,20 +204,21 @@ const app = express();
|
|
|
203
204
|
app.use(handler.getMiddleware());
|
|
204
205
|
|
|
205
206
|
app.listen(3000, () =>
|
|
206
|
-
console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`)
|
|
207
|
+
console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
|
|
207
208
|
);
|
|
208
209
|
```
|
|
209
210
|
|
|
210
211
|
### Handle the `connect` request for mqtt and reject the connection if auth failed
|
|
211
212
|
|
|
212
|
-
```
|
|
213
|
-
|
|
213
|
+
```ts snippet:ReadmeSampleConnectMqttAndReject
|
|
214
|
+
import { WebPubSubEventHandler, MqttConnectRequest } from "@azure/web-pubsub-express";
|
|
215
|
+
import express from "express";
|
|
214
216
|
|
|
215
|
-
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
216
217
|
const handler = new WebPubSubEventHandler("chat", {
|
|
217
218
|
handleConnect: (req, res) => {
|
|
218
219
|
// auth the connection and reject the connection if auth failed
|
|
219
|
-
if (req.context.clientProtocol === "mqtt") {
|
|
220
|
+
if (req.context.clientProtocol === "mqtt") {
|
|
221
|
+
// return mqtt error response when request is of MQTT kind
|
|
220
222
|
// get connect request as mqtt request and print it
|
|
221
223
|
const mqttRequest = req as MqttConnectRequest;
|
|
222
224
|
console.log(mqttRequest);
|
|
@@ -228,7 +230,7 @@ const handler = new WebPubSubEventHandler("chat", {
|
|
|
228
230
|
// res.failWith({ mqtt: { code: MqttV500ConnectReasonCode.NotAuthorized } });
|
|
229
231
|
} else res.success();
|
|
230
232
|
},
|
|
231
|
-
allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"]
|
|
233
|
+
allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"],
|
|
232
234
|
});
|
|
233
235
|
|
|
234
236
|
const app = express();
|
|
@@ -236,16 +238,16 @@ const app = express();
|
|
|
236
238
|
app.use(handler.getMiddleware());
|
|
237
239
|
|
|
238
240
|
app.listen(3000, () =>
|
|
239
|
-
console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`)
|
|
241
|
+
console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
|
|
240
242
|
);
|
|
241
243
|
```
|
|
242
244
|
|
|
243
245
|
### Handle the `onDisconnected` for mqtt request
|
|
244
246
|
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
+
```ts snippet:ReadmeSampleDisconnectedMqtt
|
|
248
|
+
import { WebPubSubEventHandler, MqttDisconnectedRequest } from "@azure/web-pubsub-express";
|
|
249
|
+
import express from "express";
|
|
247
250
|
|
|
248
|
-
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
249
251
|
const handler = new WebPubSubEventHandler("chat", {
|
|
250
252
|
onDisconnected: (disconnectedRequest) => {
|
|
251
253
|
if (disconnectedRequest.context.clientProtocol === "mqtt") {
|
|
@@ -258,7 +260,7 @@ const handler = new WebPubSubEventHandler("chat", {
|
|
|
258
260
|
// Your onDisconnected logic goes here
|
|
259
261
|
}
|
|
260
262
|
},
|
|
261
|
-
allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"]
|
|
263
|
+
allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"],
|
|
262
264
|
});
|
|
263
265
|
|
|
264
266
|
const app = express();
|
|
@@ -266,16 +268,16 @@ const app = express();
|
|
|
266
268
|
app.use(handler.getMiddleware());
|
|
267
269
|
|
|
268
270
|
app.listen(3000, () =>
|
|
269
|
-
console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`)
|
|
271
|
+
console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`),
|
|
270
272
|
);
|
|
271
273
|
```
|
|
272
274
|
|
|
273
275
|
### Only allow specified endpoints
|
|
274
276
|
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
+
```ts snippet:ReadmeSampleAllowedEndpoints
|
|
278
|
+
import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
|
|
279
|
+
import express from "express";
|
|
277
280
|
|
|
278
|
-
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
279
281
|
const handler = new WebPubSubEventHandler("chat", {
|
|
280
282
|
allowedEndpoints: [
|
|
281
283
|
"https://<yourAllowedService1>.webpubsub.azure.com",
|
|
@@ -294,10 +296,10 @@ app.listen(3000, () =>
|
|
|
294
296
|
|
|
295
297
|
### Set custom event handler path
|
|
296
298
|
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
+
```ts snippet:ReadmeSampleCustomPath
|
|
300
|
+
import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
|
|
301
|
+
import express from "express";
|
|
299
302
|
|
|
300
|
-
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
301
303
|
const handler = new WebPubSubEventHandler("chat", {
|
|
302
304
|
path: "/customPath1",
|
|
303
305
|
});
|
|
@@ -314,10 +316,9 @@ app.listen(3000, () =>
|
|
|
314
316
|
|
|
315
317
|
### Set and read connection state
|
|
316
318
|
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
319
|
+
```ts snippet:ReadmeSampleState
|
|
320
|
+
import { WebPubSubEventHandler } from "@azure/web-pubsub-express";
|
|
321
|
+
import express from "express";
|
|
321
322
|
|
|
322
323
|
const handler = new WebPubSubEventHandler("chat", {
|
|
323
324
|
handleConnect(req, res) {
|
|
@@ -347,14 +348,20 @@ app.listen(3000, () =>
|
|
|
347
348
|
|
|
348
349
|
### Enable logs
|
|
349
350
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
- Getting debug logs from the SignalR client library
|
|
351
|
+
Enabling logging may help uncover useful information about failures. In order to see a log of HTTP requests and responses, set the `AZURE_LOG_LEVEL` environment variable to `info`.
|
|
353
352
|
|
|
354
353
|
```bash
|
|
355
354
|
export AZURE_LOG_LEVEL=verbose
|
|
356
355
|
```
|
|
357
356
|
|
|
357
|
+
Alternatively, logging can be enabled at runtime by calling `setLogLevel` in the `@azure/logger`:
|
|
358
|
+
|
|
359
|
+
```ts snippet:SetLogLevel
|
|
360
|
+
import { setLogLevel } from "@azure/logger";
|
|
361
|
+
|
|
362
|
+
setLogLevel("info");
|
|
363
|
+
```
|
|
364
|
+
|
|
358
365
|
For more detailed instructions on how to enable logs, you can look at the [@azure/logger package docs](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger).
|
|
359
366
|
|
|
360
367
|
### Live Trace
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
import type { WebPubSubEventHandlerOptions } from "./cloudEventsProtocols.js";
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare class CloudEventsDispatcher {
|
|
7
|
+
private hub;
|
|
8
|
+
private eventHandler?;
|
|
9
|
+
private readonly _allowAll;
|
|
10
|
+
private readonly _allowedOrigins;
|
|
11
|
+
constructor(hub: string, eventHandler?: WebPubSubEventHandlerOptions | undefined);
|
|
12
|
+
handlePreflight(req: IncomingMessage, res: ServerResponse): boolean;
|
|
13
|
+
handleRequest(request: IncomingMessage, response: ServerResponse): Promise<boolean>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=cloudEventsDispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudEventsDispatcher.d.ts","sourceRoot":"","sources":["../../src/cloudEventsDispatcher.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAIjE,OAAO,KAAK,EASV,4BAA4B,EAM7B,MAAM,2BAA2B,CAAC;AAuTnC;;GAEG;AACH,qBAAa,qBAAqB;IAI9B,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,YAAY,CAAC;IAJvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;gBAE3C,GAAG,EAAE,MAAM,EACX,YAAY,CAAC,EAAE,4BAA4B,YAAA;IAa9C,eAAe,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO;IAoB7D,aAAa,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;CA2GjG"}
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
import * as utils from "./utils.js";
|
|
4
|
+
import { URL } from "node:url";
|
|
5
|
+
import { logger } from "./logger.js";
|
|
6
|
+
import { MqttV311ConnectReturnCode } from "./enum/MqttErrorCodes/mqttV311ConnectReturnCode.js";
|
|
7
|
+
import { MqttV500ConnectReasonCode } from "./enum/MqttErrorCodes/mqttV500ConnectReasonCode.js";
|
|
8
|
+
var EventType;
|
|
9
|
+
(function (EventType) {
|
|
10
|
+
EventType[EventType["Connect"] = 0] = "Connect";
|
|
11
|
+
EventType[EventType["Connected"] = 1] = "Connected";
|
|
12
|
+
EventType[EventType["Disconnected"] = 2] = "Disconnected";
|
|
13
|
+
EventType[EventType["UserEvent"] = 3] = "UserEvent";
|
|
14
|
+
})(EventType || (EventType = {}));
|
|
15
|
+
function getConnectResponseHandler(connectRequest, response) {
|
|
16
|
+
const states = connectRequest.context.states;
|
|
17
|
+
let modified = false;
|
|
18
|
+
const handler = {
|
|
19
|
+
setState(name, value) {
|
|
20
|
+
states[name] = value;
|
|
21
|
+
modified = true;
|
|
22
|
+
},
|
|
23
|
+
success(res) {
|
|
24
|
+
if (modified) {
|
|
25
|
+
response.setHeader("ce-connectionState", utils.toBase64JsonString(states));
|
|
26
|
+
}
|
|
27
|
+
if (res === undefined) {
|
|
28
|
+
response.statusCode = 204;
|
|
29
|
+
response.end();
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
response.statusCode = 200;
|
|
33
|
+
response.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
34
|
+
response.end(JSON.stringify(res));
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
fail(code, detail) {
|
|
38
|
+
handleConnectErrorResponse(connectRequest, response, code, detail);
|
|
39
|
+
},
|
|
40
|
+
failWith(res) {
|
|
41
|
+
if ("mqtt" in res) {
|
|
42
|
+
response.statusCode = getStatusCodeFromMqttConnectCode(res.mqtt.code);
|
|
43
|
+
response.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
44
|
+
response.end(JSON.stringify(res));
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
handleConnectErrorResponse(connectRequest, response, res.code, res.detail);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
return handler;
|
|
52
|
+
}
|
|
53
|
+
function getUserEventResponseHandler(userRequest, response) {
|
|
54
|
+
const states = userRequest.context.states;
|
|
55
|
+
let modified = false;
|
|
56
|
+
const handler = {
|
|
57
|
+
setState(name, value) {
|
|
58
|
+
modified = true;
|
|
59
|
+
states[name] = value;
|
|
60
|
+
},
|
|
61
|
+
success(data, dataType) {
|
|
62
|
+
response.statusCode = 200;
|
|
63
|
+
if (modified) {
|
|
64
|
+
response.setHeader("ce-connectionState", utils.toBase64JsonString(states));
|
|
65
|
+
}
|
|
66
|
+
switch (dataType) {
|
|
67
|
+
case "json":
|
|
68
|
+
response.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
69
|
+
break;
|
|
70
|
+
case "text":
|
|
71
|
+
response.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
72
|
+
break;
|
|
73
|
+
default:
|
|
74
|
+
response.setHeader("Content-Type", "application/octet-stream");
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
response.end(data !== null && data !== void 0 ? data : "");
|
|
78
|
+
},
|
|
79
|
+
fail(code, detail) {
|
|
80
|
+
response.statusCode = code;
|
|
81
|
+
response.end(detail !== null && detail !== void 0 ? detail : "");
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
return handler;
|
|
85
|
+
}
|
|
86
|
+
function getContext(request, origin) {
|
|
87
|
+
const baseContext = {
|
|
88
|
+
signature: utils.getHttpHeader(request, "ce-signature"),
|
|
89
|
+
userId: utils.getHttpHeader(request, "ce-userid"),
|
|
90
|
+
hub: utils.getHttpHeader(request, "ce-hub"),
|
|
91
|
+
connectionId: utils.getHttpHeader(request, "ce-connectionid"),
|
|
92
|
+
eventName: utils.getHttpHeader(request, "ce-eventname"),
|
|
93
|
+
origin: origin,
|
|
94
|
+
states: utils.fromBase64JsonString(utils.getHttpHeader(request, "ce-connectionstate")),
|
|
95
|
+
clientProtocol: "default",
|
|
96
|
+
};
|
|
97
|
+
if (isMqttRequest(request)) {
|
|
98
|
+
const mqttProperties = {
|
|
99
|
+
physicalConnectionId: utils.getHttpHeader(request, "ce-physicalConnectionId"),
|
|
100
|
+
sessionId: utils.getHttpHeader(request, "ce-sessionId"),
|
|
101
|
+
};
|
|
102
|
+
return Object.assign(Object.assign({}, baseContext), { clientProtocol: "mqtt", mqtt: mqttProperties });
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
return baseContext;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function tryGetWebPubSubEvent(req) {
|
|
109
|
+
// check ce-type to see if it is a valid WebPubSub CloudEvent request
|
|
110
|
+
const prefix = "azure.webpubsub.";
|
|
111
|
+
const connect = "azure.webpubsub.sys.connect";
|
|
112
|
+
const connected = "azure.webpubsub.sys.connected";
|
|
113
|
+
const disconnectd = "azure.webpubsub.sys.disconnected";
|
|
114
|
+
const userPrefix = "azure.webpubsub.user.";
|
|
115
|
+
const type = utils.getHttpHeader(req, "ce-type");
|
|
116
|
+
if (!(type === null || type === void 0 ? void 0 : type.startsWith(prefix))) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
if (type.startsWith(userPrefix)) {
|
|
120
|
+
return EventType.UserEvent;
|
|
121
|
+
}
|
|
122
|
+
switch (type) {
|
|
123
|
+
case connect:
|
|
124
|
+
return EventType.Connect;
|
|
125
|
+
case connected:
|
|
126
|
+
return EventType.Connected;
|
|
127
|
+
case disconnectd:
|
|
128
|
+
return EventType.Disconnected;
|
|
129
|
+
default:
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function getStatusCodeFromMqttConnectCode(mqttConnectCode) {
|
|
134
|
+
if (mqttConnectCode < 0x80) {
|
|
135
|
+
switch (mqttConnectCode) {
|
|
136
|
+
case MqttV311ConnectReturnCode.UnacceptableProtocolVersion:
|
|
137
|
+
case MqttV311ConnectReturnCode.IdentifierRejected:
|
|
138
|
+
return 400; // BadRequest
|
|
139
|
+
case MqttV311ConnectReturnCode.ServerUnavailable:
|
|
140
|
+
return 503; // ServiceUnavailable
|
|
141
|
+
case MqttV311ConnectReturnCode.BadUsernameOrPassword:
|
|
142
|
+
case MqttV311ConnectReturnCode.NotAuthorized:
|
|
143
|
+
return 401; // Unauthorized
|
|
144
|
+
default:
|
|
145
|
+
logger.warning(`Invalid MQTT connect return code: ${mqttConnectCode}.`);
|
|
146
|
+
return 500; // InternalServerError
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
switch (mqttConnectCode) {
|
|
151
|
+
case MqttV500ConnectReasonCode.NotAuthorized:
|
|
152
|
+
case MqttV500ConnectReasonCode.BadUserNameOrPassword:
|
|
153
|
+
return 401; // Unauthorized
|
|
154
|
+
case MqttV500ConnectReasonCode.ClientIdentifierNotValid:
|
|
155
|
+
case MqttV500ConnectReasonCode.MalformedPacket:
|
|
156
|
+
case MqttV500ConnectReasonCode.UnsupportedProtocolVersion:
|
|
157
|
+
case MqttV500ConnectReasonCode.BadAuthenticationMethod:
|
|
158
|
+
case MqttV500ConnectReasonCode.TopicNameInvalid:
|
|
159
|
+
case MqttV500ConnectReasonCode.PayloadFormatInvalid:
|
|
160
|
+
case MqttV500ConnectReasonCode.ImplementationSpecificError:
|
|
161
|
+
case MqttV500ConnectReasonCode.PacketTooLarge:
|
|
162
|
+
case MqttV500ConnectReasonCode.RetainNotSupported:
|
|
163
|
+
case MqttV500ConnectReasonCode.QosNotSupported:
|
|
164
|
+
return 400; // BadRequest
|
|
165
|
+
case MqttV500ConnectReasonCode.QuotaExceeded:
|
|
166
|
+
case MqttV500ConnectReasonCode.ConnectionRateExceeded:
|
|
167
|
+
return 429; // TooManyRequests
|
|
168
|
+
case MqttV500ConnectReasonCode.Banned:
|
|
169
|
+
return 403; // Forbidden
|
|
170
|
+
case MqttV500ConnectReasonCode.UseAnotherServer:
|
|
171
|
+
case MqttV500ConnectReasonCode.ServerMoved:
|
|
172
|
+
case MqttV500ConnectReasonCode.ServerUnavailable:
|
|
173
|
+
case MqttV500ConnectReasonCode.ServerBusy:
|
|
174
|
+
case MqttV500ConnectReasonCode.UnspecifiedError:
|
|
175
|
+
return 500; // InternalServerError
|
|
176
|
+
default:
|
|
177
|
+
logger.warning(`Invalid MQTT connect return code: ${mqttConnectCode}.`);
|
|
178
|
+
return 500; // InternalServerError
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function getMqttConnectCodeFromStatusCode(statusCode, protocolVersion) {
|
|
183
|
+
if (protocolVersion === 4) {
|
|
184
|
+
switch (statusCode) {
|
|
185
|
+
case 400:
|
|
186
|
+
return MqttV311ConnectReturnCode.BadUsernameOrPassword;
|
|
187
|
+
case 401:
|
|
188
|
+
return MqttV311ConnectReturnCode.NotAuthorized;
|
|
189
|
+
case 500:
|
|
190
|
+
return MqttV311ConnectReturnCode.ServerUnavailable;
|
|
191
|
+
default:
|
|
192
|
+
logger.warning(`Unsupported HTTP Status Code: ${statusCode}.`);
|
|
193
|
+
return MqttV311ConnectReturnCode.ServerUnavailable;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else if (protocolVersion === 5) {
|
|
197
|
+
switch (statusCode) {
|
|
198
|
+
case 400:
|
|
199
|
+
return MqttV500ConnectReasonCode.BadUserNameOrPassword;
|
|
200
|
+
case 401:
|
|
201
|
+
return MqttV500ConnectReasonCode.NotAuthorized;
|
|
202
|
+
case 500:
|
|
203
|
+
return MqttV500ConnectReasonCode.UnspecifiedError;
|
|
204
|
+
default:
|
|
205
|
+
logger.warning(`Unsupported HTTP Status Code: ${statusCode}.`);
|
|
206
|
+
return MqttV500ConnectReasonCode.UnspecifiedError;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
logger.warning(`Invalid MQTT protocol version: ${protocolVersion}.`);
|
|
211
|
+
return MqttV311ConnectReturnCode.UnacceptableProtocolVersion;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function handleConnectErrorResponse(connectRequest, response, code, detail) {
|
|
215
|
+
const isMqttReq = connectRequest.context.clientProtocol === "mqtt";
|
|
216
|
+
if (isMqttReq) {
|
|
217
|
+
const protocolVersion = connectRequest.mqtt.protocolVersion;
|
|
218
|
+
const mqttErrorResponse = {
|
|
219
|
+
mqtt: {
|
|
220
|
+
code: getMqttConnectCodeFromStatusCode(code, protocolVersion),
|
|
221
|
+
reason: detail,
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
response.statusCode = code;
|
|
225
|
+
response.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
226
|
+
response.end(JSON.stringify(mqttErrorResponse));
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
response.statusCode = code;
|
|
230
|
+
response.end(detail !== null && detail !== void 0 ? detail : "");
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function isWebPubSubRequest(req) {
|
|
234
|
+
return utils.getHttpHeader(req, "ce-awpsversion") !== undefined;
|
|
235
|
+
}
|
|
236
|
+
function isMqttRequest(req) {
|
|
237
|
+
const subprotocol = utils.getHttpHeader(req, "ce-subprotocol");
|
|
238
|
+
const physicalConnectionId = utils.getHttpHeader(req, "ce-physicalConnectionId");
|
|
239
|
+
return (subprotocol !== undefined &&
|
|
240
|
+
subprotocol.toLowerCase().includes("mqtt") &&
|
|
241
|
+
physicalConnectionId !== undefined);
|
|
242
|
+
}
|
|
243
|
+
async function readUserEventRequest(request, origin) {
|
|
244
|
+
const contentTypeheader = utils.getHttpHeader(request, "content-type");
|
|
245
|
+
if (contentTypeheader === undefined) {
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
248
|
+
const contentType = contentTypeheader.split(";")[0].trim();
|
|
249
|
+
switch (contentType) {
|
|
250
|
+
case "application/octet-stream":
|
|
251
|
+
return {
|
|
252
|
+
context: getContext(request, origin),
|
|
253
|
+
data: await utils.readRequestBody(request),
|
|
254
|
+
dataType: "binary",
|
|
255
|
+
};
|
|
256
|
+
case "application/json":
|
|
257
|
+
return {
|
|
258
|
+
context: getContext(request, origin),
|
|
259
|
+
data: JSON.parse((await utils.readRequestBody(request)).toString()),
|
|
260
|
+
dataType: "json",
|
|
261
|
+
};
|
|
262
|
+
case "text/plain":
|
|
263
|
+
return {
|
|
264
|
+
context: getContext(request, origin),
|
|
265
|
+
data: (await utils.readRequestBody(request)).toString(),
|
|
266
|
+
dataType: "text",
|
|
267
|
+
};
|
|
268
|
+
default:
|
|
269
|
+
return undefined;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async function readSystemEventRequest(request, origin) {
|
|
273
|
+
const body = (await utils.readRequestBody(request)).toString();
|
|
274
|
+
const parsedRequest = JSON.parse(body);
|
|
275
|
+
parsedRequest.context = getContext(request, origin);
|
|
276
|
+
return parsedRequest;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* @internal
|
|
280
|
+
*/
|
|
281
|
+
export class CloudEventsDispatcher {
|
|
282
|
+
constructor(hub, eventHandler) {
|
|
283
|
+
this.hub = hub;
|
|
284
|
+
this.eventHandler = eventHandler;
|
|
285
|
+
this._allowAll = true;
|
|
286
|
+
this._allowedOrigins = [];
|
|
287
|
+
if (Array.isArray(eventHandler)) {
|
|
288
|
+
throw new Error("Unexpected WebPubSubEventHandlerOptions");
|
|
289
|
+
}
|
|
290
|
+
if ((eventHandler === null || eventHandler === void 0 ? void 0 : eventHandler.allowedEndpoints) !== undefined) {
|
|
291
|
+
this._allowedOrigins = eventHandler.allowedEndpoints.map((endpoint) => new URL(endpoint).host.toLowerCase());
|
|
292
|
+
this._allowAll = false;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
handlePreflight(req, res) {
|
|
296
|
+
if (!isWebPubSubRequest(req)) {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
const origin = utils.getHttpHeader(req, "webhook-request-origin");
|
|
300
|
+
if (origin === undefined) {
|
|
301
|
+
logger.warning("Expecting webhook-request-origin header.");
|
|
302
|
+
res.statusCode = 400;
|
|
303
|
+
}
|
|
304
|
+
else if (this._allowAll) {
|
|
305
|
+
res.setHeader("WebHook-Allowed-Origin", "*");
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
// service to do the check
|
|
309
|
+
res.setHeader("WebHook-Allowed-Origin", this._allowedOrigins);
|
|
310
|
+
}
|
|
311
|
+
res.end();
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
async handleRequest(request, response) {
|
|
315
|
+
var _a, _b, _c, _d;
|
|
316
|
+
if (!isWebPubSubRequest(request)) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
// check if it is a valid WebPubSub cloud events
|
|
320
|
+
const origin = utils.getHttpHeader(request, "webhook-request-origin");
|
|
321
|
+
if (origin === undefined) {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
const eventType = tryGetWebPubSubEvent(request);
|
|
325
|
+
if (eventType === undefined) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
// check if hub matches
|
|
329
|
+
const hub = utils.getHttpHeader(request, "ce-hub");
|
|
330
|
+
if ((hub === null || hub === void 0 ? void 0 : hub.toUpperCase()) !== this.hub.toUpperCase()) {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
const isMqtt = isMqttRequest(request);
|
|
334
|
+
// No need to read body if handler is not specified
|
|
335
|
+
switch (eventType) {
|
|
336
|
+
case EventType.Connect:
|
|
337
|
+
if (!((_a = this.eventHandler) === null || _a === void 0 ? void 0 : _a.handleConnect)) {
|
|
338
|
+
if (isMqtt)
|
|
339
|
+
response.statusCode = 204;
|
|
340
|
+
response.end();
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
break;
|
|
344
|
+
case EventType.Connected:
|
|
345
|
+
if (!((_b = this.eventHandler) === null || _b === void 0 ? void 0 : _b.onConnected)) {
|
|
346
|
+
response.end();
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
break;
|
|
350
|
+
case EventType.Disconnected:
|
|
351
|
+
if (!((_c = this.eventHandler) === null || _c === void 0 ? void 0 : _c.onDisconnected)) {
|
|
352
|
+
response.end();
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
break;
|
|
356
|
+
case EventType.UserEvent:
|
|
357
|
+
if (!((_d = this.eventHandler) === null || _d === void 0 ? void 0 : _d.handleUserEvent)) {
|
|
358
|
+
response.end();
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
361
|
+
break;
|
|
362
|
+
default:
|
|
363
|
+
logger.warning(`Unknown EventType ${eventType}`);
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
switch (eventType) {
|
|
367
|
+
case EventType.Connect: {
|
|
368
|
+
const connectRequest = isMqtt
|
|
369
|
+
? await readSystemEventRequest(request, origin)
|
|
370
|
+
: await readSystemEventRequest(request, origin);
|
|
371
|
+
// service passes out query property, assign it to queries
|
|
372
|
+
connectRequest.queries = connectRequest.query;
|
|
373
|
+
logger.verbose(connectRequest);
|
|
374
|
+
this.eventHandler.handleConnect(connectRequest, getConnectResponseHandler(connectRequest, response));
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
case EventType.Connected: {
|
|
378
|
+
// for unblocking events, we responds to the service as early as possible
|
|
379
|
+
response.end();
|
|
380
|
+
const connectedRequest = await readSystemEventRequest(request, origin);
|
|
381
|
+
logger.verbose(connectedRequest);
|
|
382
|
+
this.eventHandler.onConnected(connectedRequest);
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
case EventType.Disconnected: {
|
|
386
|
+
// for unblocking events, we responds to the service as early as possible
|
|
387
|
+
response.end();
|
|
388
|
+
const disconnectedRequest = isMqtt
|
|
389
|
+
? await readSystemEventRequest(request, origin)
|
|
390
|
+
: await readSystemEventRequest(request, origin);
|
|
391
|
+
logger.verbose(disconnectedRequest);
|
|
392
|
+
this.eventHandler.onDisconnected(disconnectedRequest);
|
|
393
|
+
return true;
|
|
394
|
+
}
|
|
395
|
+
case EventType.UserEvent: {
|
|
396
|
+
const userRequest = await readUserEventRequest(request, origin);
|
|
397
|
+
if (userRequest === undefined) {
|
|
398
|
+
logger.warning(`Unsupported content type ${utils.getHttpHeader(request, "content-type")}`);
|
|
399
|
+
return false;
|
|
400
|
+
}
|
|
401
|
+
logger.verbose(userRequest);
|
|
402
|
+
this.eventHandler.handleUserEvent(userRequest, getUserEventResponseHandler(userRequest, response));
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
default:
|
|
406
|
+
logger.warning(`Unknown EventType ${eventType}`);
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
//# sourceMappingURL=cloudEventsDispatcher.js.map
|