@azure/web-pubsub-express 1.0.6-alpha.20240930.1 → 1.0.6-alpha.20241002.1
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 +165 -0
- package/dist/commonjs/cloudEventsDispatcher.d.ts.map +1 -1
- package/dist/commonjs/cloudEventsDispatcher.js +143 -8
- package/dist/commonjs/cloudEventsDispatcher.js.map +1 -1
- package/dist/commonjs/cloudEventsProtocols.d.ts +174 -1
- package/dist/commonjs/cloudEventsProtocols.d.ts.map +1 -1
- package/dist/commonjs/cloudEventsProtocols.js.map +1 -1
- package/dist/commonjs/enum/MqttErrorCodes/mqttDisconnectReasonCode.d.ts +180 -0
- package/dist/commonjs/enum/MqttErrorCodes/mqttDisconnectReasonCode.d.ts.map +1 -0
- package/dist/commonjs/enum/MqttErrorCodes/mqttDisconnectReasonCode.js +186 -0
- package/dist/commonjs/enum/MqttErrorCodes/mqttDisconnectReasonCode.js.map +1 -0
- package/dist/commonjs/enum/MqttErrorCodes/mqttV311ConnectReturnCode.d.ts +31 -0
- package/dist/commonjs/enum/MqttErrorCodes/mqttV311ConnectReturnCode.d.ts.map +1 -0
- package/dist/commonjs/enum/MqttErrorCodes/mqttV311ConnectReturnCode.js +37 -0
- package/dist/commonjs/enum/MqttErrorCodes/mqttV311ConnectReturnCode.js.map +1 -0
- package/dist/commonjs/enum/MqttErrorCodes/mqttV500ConnectReasonCode.d.ts +112 -0
- package/dist/commonjs/enum/MqttErrorCodes/mqttV500ConnectReasonCode.d.ts.map +1 -0
- package/dist/commonjs/enum/MqttErrorCodes/mqttV500ConnectReasonCode.js +118 -0
- package/dist/commonjs/enum/MqttErrorCodes/mqttV500ConnectReasonCode.js.map +1 -0
- package/dist/commonjs/index.d.ts +3 -0
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +473 -8
- package/dist/commonjs/index.js.map +1 -1
- package/dist/esm/cloudEventsDispatcher.d.ts.map +1 -1
- package/dist/esm/cloudEventsDispatcher.js +143 -8
- package/dist/esm/cloudEventsDispatcher.js.map +1 -1
- package/dist/esm/cloudEventsProtocols.d.ts +174 -1
- package/dist/esm/cloudEventsProtocols.d.ts.map +1 -1
- package/dist/esm/cloudEventsProtocols.js.map +1 -1
- package/dist/esm/enum/MqttErrorCodes/mqttDisconnectReasonCode.d.ts +180 -0
- package/dist/esm/enum/MqttErrorCodes/mqttDisconnectReasonCode.d.ts.map +1 -0
- package/dist/esm/enum/MqttErrorCodes/mqttDisconnectReasonCode.js +183 -0
- package/dist/esm/enum/MqttErrorCodes/mqttDisconnectReasonCode.js.map +1 -0
- package/dist/esm/enum/MqttErrorCodes/mqttV311ConnectReturnCode.d.ts +31 -0
- package/dist/esm/enum/MqttErrorCodes/mqttV311ConnectReturnCode.d.ts.map +1 -0
- package/dist/esm/enum/MqttErrorCodes/mqttV311ConnectReturnCode.js +34 -0
- package/dist/esm/enum/MqttErrorCodes/mqttV311ConnectReturnCode.js.map +1 -0
- package/dist/esm/enum/MqttErrorCodes/mqttV500ConnectReasonCode.d.ts +112 -0
- package/dist/esm/enum/MqttErrorCodes/mqttV500ConnectReasonCode.d.ts.map +1 -0
- package/dist/esm/enum/MqttErrorCodes/mqttV500ConnectReasonCode.js +115 -0
- package/dist/esm/enum/MqttErrorCodes/mqttV500ConnectReasonCode.js.map +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/web-pubsub-express.d.ts +507 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -102,6 +102,171 @@ app.listen(3000, () =>
|
|
|
102
102
|
);
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
+
### Handle the `connect` request and reject the connection if auth failed
|
|
106
|
+
```js
|
|
107
|
+
const express = require("express");
|
|
108
|
+
|
|
109
|
+
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
110
|
+
const handler = new WebPubSubEventHandler("chat", {
|
|
111
|
+
handleConnect: (req, res) => {
|
|
112
|
+
// auth the connection and reject the connection if auth failed
|
|
113
|
+
res.fail(401, "Unauthorized");
|
|
114
|
+
// the following method is also a valid approach
|
|
115
|
+
// res.failWith({ code: 401, detail: "Unauthorized" });
|
|
116
|
+
},
|
|
117
|
+
allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"]
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const app = express();
|
|
121
|
+
|
|
122
|
+
app.use(handler.getMiddleware());
|
|
123
|
+
|
|
124
|
+
app.listen(3000, () =>
|
|
125
|
+
console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`)
|
|
126
|
+
);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Handle the `connected` request
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
const express = require("express");
|
|
133
|
+
|
|
134
|
+
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
135
|
+
const handler = new WebPubSubEventHandler("chat", {
|
|
136
|
+
onConnected: (connectedRequest) => {
|
|
137
|
+
// Your onConnected logic goes here
|
|
138
|
+
},
|
|
139
|
+
allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"]
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const app = express();
|
|
143
|
+
|
|
144
|
+
app.use(handler.getMiddleware());
|
|
145
|
+
|
|
146
|
+
app.listen(3000, () =>
|
|
147
|
+
console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`)
|
|
148
|
+
);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Handle the `onDisconnected` request
|
|
152
|
+
|
|
153
|
+
```js
|
|
154
|
+
const express = require("express");
|
|
155
|
+
|
|
156
|
+
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
157
|
+
const handler = new WebPubSubEventHandler("chat", {
|
|
158
|
+
onDisconnected: (disconnectedRequest) => {
|
|
159
|
+
// Your onDisconnected logic goes here
|
|
160
|
+
},
|
|
161
|
+
allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"]
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const app = express();
|
|
165
|
+
|
|
166
|
+
app.use(handler.getMiddleware());
|
|
167
|
+
|
|
168
|
+
app.listen(3000, () =>
|
|
169
|
+
console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`)
|
|
170
|
+
);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Handle the `connect` request for mqtt and assign `<userId>` and `<mqtt>` properties
|
|
174
|
+
```js
|
|
175
|
+
const express = require("express");
|
|
176
|
+
|
|
177
|
+
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
178
|
+
const handler = new WebPubSubEventHandler("chat", {
|
|
179
|
+
handleConnect: (req, res) => {
|
|
180
|
+
if (req.context.clientProtocol === "mqtt") { // return mqtt response when request is of MQTT kind
|
|
181
|
+
// get connect request as mqtt request and print it
|
|
182
|
+
const mqttRequest = req as MqttConnectRequest;
|
|
183
|
+
console.log(mqttRequest);
|
|
184
|
+
|
|
185
|
+
// auth the connection and return mqtt response
|
|
186
|
+
res.success({
|
|
187
|
+
userId: "user1",
|
|
188
|
+
mqtt: { userProperties: [{ name: "a", value: "b" }] },
|
|
189
|
+
});
|
|
190
|
+
} else {
|
|
191
|
+
res.success({
|
|
192
|
+
userId: "user1",
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"]
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const app = express();
|
|
200
|
+
|
|
201
|
+
app.use(handler.getMiddleware());
|
|
202
|
+
|
|
203
|
+
app.listen(3000, () =>
|
|
204
|
+
console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`)
|
|
205
|
+
);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Handle the `connect` request for mqtt and reject the connection if auth failed
|
|
209
|
+
```js
|
|
210
|
+
const express = require("express");
|
|
211
|
+
|
|
212
|
+
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
213
|
+
const handler = new WebPubSubEventHandler("chat", {
|
|
214
|
+
handleConnect: (req, res) => {
|
|
215
|
+
// auth the connection and reject the connection if auth failed
|
|
216
|
+
if (req.context.clientProtocol === "mqtt") { // return mqtt error response when request is of MQTT kind
|
|
217
|
+
// get connect request as mqtt request and print it
|
|
218
|
+
const mqttRequest = req as MqttConnectRequest;
|
|
219
|
+
console.log(mqttRequest);
|
|
220
|
+
|
|
221
|
+
// auth the connection and return mqtt failure response
|
|
222
|
+
res.fail(401, "Not Authorized");
|
|
223
|
+
|
|
224
|
+
// Or use below method for more fine-grained control over the MQTT return code
|
|
225
|
+
// res.failWith({ mqtt: { code: MqttV500ConnectReasonCode.NotAuthorized } });
|
|
226
|
+
} else res.success();
|
|
227
|
+
},
|
|
228
|
+
allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"]
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
const app = express();
|
|
232
|
+
|
|
233
|
+
app.use(handler.getMiddleware());
|
|
234
|
+
|
|
235
|
+
app.listen(3000, () =>
|
|
236
|
+
console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`)
|
|
237
|
+
);
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Handle the `onDisconnected` for mqtt request
|
|
241
|
+
|
|
242
|
+
```js
|
|
243
|
+
const express = require("express");
|
|
244
|
+
|
|
245
|
+
const { WebPubSubEventHandler } = require("@azure/web-pubsub-express");
|
|
246
|
+
const handler = new WebPubSubEventHandler("chat", {
|
|
247
|
+
onDisconnected: (disconnectedRequest) => {
|
|
248
|
+
if (disconnectedRequest.context.clientProtocol === "mqtt") {
|
|
249
|
+
// get disconnect request as mqtt request and print it
|
|
250
|
+
const mqttRequest = disconnectedRequest as MqttDisconnectedRequest;
|
|
251
|
+
console.log(mqttRequest.mqtt);
|
|
252
|
+
// Your onDisconnected logic goes here
|
|
253
|
+
} else {
|
|
254
|
+
console.log(disconnectedRequest);
|
|
255
|
+
// Your onDisconnected logic goes here
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
allowedEndpoints: ["https://<yourAllowedService>.webpubsub.azure.com"]
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
const app = express();
|
|
262
|
+
|
|
263
|
+
app.use(handler.getMiddleware());
|
|
264
|
+
|
|
265
|
+
app.listen(3000, () =>
|
|
266
|
+
console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`)
|
|
267
|
+
);
|
|
268
|
+
```
|
|
269
|
+
|
|
105
270
|
### Only allow specified endpoints
|
|
106
271
|
|
|
107
272
|
```js
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudEventsDispatcher.d.ts","sourceRoot":"","sources":["../../src/cloudEventsDispatcher.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAI5D,OAAO,KAAK,EASV,4BAA4B,
|
|
1
|
+
{"version":3,"file":"cloudEventsDispatcher.d.ts","sourceRoot":"","sources":["../../src/cloudEventsDispatcher.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAI5D,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"}
|
|
@@ -7,6 +7,8 @@ const tslib_1 = require("tslib");
|
|
|
7
7
|
const utils = tslib_1.__importStar(require("./utils.js"));
|
|
8
8
|
const node_url_1 = require("node:url");
|
|
9
9
|
const logger_js_1 = require("./logger.js");
|
|
10
|
+
const mqttV311ConnectReturnCode_js_1 = require("./enum/MqttErrorCodes/mqttV311ConnectReturnCode.js");
|
|
11
|
+
const mqttV500ConnectReasonCode_js_1 = require("./enum/MqttErrorCodes/mqttV500ConnectReasonCode.js");
|
|
10
12
|
var EventType;
|
|
11
13
|
(function (EventType) {
|
|
12
14
|
EventType[EventType["Connect"] = 0] = "Connect";
|
|
@@ -23,21 +25,31 @@ function getConnectResponseHandler(connectRequest, response) {
|
|
|
23
25
|
modified = true;
|
|
24
26
|
},
|
|
25
27
|
success(res) {
|
|
26
|
-
response.statusCode = 200;
|
|
27
28
|
if (modified) {
|
|
28
29
|
response.setHeader("ce-connectionState", utils.toBase64JsonString(states));
|
|
29
30
|
}
|
|
30
31
|
if (res === undefined) {
|
|
32
|
+
response.statusCode = 204;
|
|
31
33
|
response.end();
|
|
32
34
|
}
|
|
33
35
|
else {
|
|
36
|
+
response.statusCode = 200;
|
|
34
37
|
response.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
35
38
|
response.end(JSON.stringify(res));
|
|
36
39
|
}
|
|
37
40
|
},
|
|
38
41
|
fail(code, detail) {
|
|
39
|
-
response
|
|
40
|
-
|
|
42
|
+
handleConnectErrorResponse(connectRequest, response, code, detail);
|
|
43
|
+
},
|
|
44
|
+
failWith(res) {
|
|
45
|
+
if ("mqtt" in res) {
|
|
46
|
+
response.statusCode = getStatusCodeFromMqttConnectCode(res.mqtt.code);
|
|
47
|
+
response.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
48
|
+
response.end(JSON.stringify(res));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
handleConnectErrorResponse(connectRequest, response, res.code, res.detail);
|
|
52
|
+
}
|
|
41
53
|
},
|
|
42
54
|
};
|
|
43
55
|
return handler;
|
|
@@ -76,7 +88,7 @@ function getUserEventResponseHandler(userRequest, response) {
|
|
|
76
88
|
return handler;
|
|
77
89
|
}
|
|
78
90
|
function getContext(request, origin) {
|
|
79
|
-
const
|
|
91
|
+
const baseContext = {
|
|
80
92
|
signature: utils.getHttpHeader(request, "ce-signature"),
|
|
81
93
|
userId: utils.getHttpHeader(request, "ce-userid"),
|
|
82
94
|
hub: utils.getHttpHeader(request, "ce-hub"),
|
|
@@ -84,9 +96,18 @@ function getContext(request, origin) {
|
|
|
84
96
|
eventName: utils.getHttpHeader(request, "ce-eventname"),
|
|
85
97
|
origin: origin,
|
|
86
98
|
states: utils.fromBase64JsonString(utils.getHttpHeader(request, "ce-connectionstate")),
|
|
99
|
+
clientProtocol: "default",
|
|
87
100
|
};
|
|
88
|
-
|
|
89
|
-
|
|
101
|
+
if (isMqttRequest(request)) {
|
|
102
|
+
const mqttProperties = {
|
|
103
|
+
physicalConnectionId: utils.getHttpHeader(request, "ce-physicalConnectionId"),
|
|
104
|
+
sessionId: utils.getHttpHeader(request, "ce-sessionId"),
|
|
105
|
+
};
|
|
106
|
+
return Object.assign(Object.assign({}, baseContext), { clientProtocol: "mqtt", mqtt: mqttProperties });
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
return baseContext;
|
|
110
|
+
}
|
|
90
111
|
}
|
|
91
112
|
function tryGetWebPubSubEvent(req) {
|
|
92
113
|
// check ce-type to see if it is a valid WebPubSub CloudEvent request
|
|
@@ -113,9 +134,116 @@ function tryGetWebPubSubEvent(req) {
|
|
|
113
134
|
return undefined;
|
|
114
135
|
}
|
|
115
136
|
}
|
|
137
|
+
function getStatusCodeFromMqttConnectCode(mqttConnectCode) {
|
|
138
|
+
if (mqttConnectCode < 0x80) {
|
|
139
|
+
switch (mqttConnectCode) {
|
|
140
|
+
case mqttV311ConnectReturnCode_js_1.MqttV311ConnectReturnCode.UnacceptableProtocolVersion:
|
|
141
|
+
case mqttV311ConnectReturnCode_js_1.MqttV311ConnectReturnCode.IdentifierRejected:
|
|
142
|
+
return 400; // BadRequest
|
|
143
|
+
case mqttV311ConnectReturnCode_js_1.MqttV311ConnectReturnCode.ServerUnavailable:
|
|
144
|
+
return 503; // ServiceUnavailable
|
|
145
|
+
case mqttV311ConnectReturnCode_js_1.MqttV311ConnectReturnCode.BadUsernameOrPassword:
|
|
146
|
+
case mqttV311ConnectReturnCode_js_1.MqttV311ConnectReturnCode.NotAuthorized:
|
|
147
|
+
return 401; // Unauthorized
|
|
148
|
+
default:
|
|
149
|
+
logger_js_1.logger.warning(`Invalid MQTT connect return code: ${mqttConnectCode}.`);
|
|
150
|
+
return 500; // InternalServerError
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
switch (mqttConnectCode) {
|
|
155
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.NotAuthorized:
|
|
156
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.BadUserNameOrPassword:
|
|
157
|
+
return 401; // Unauthorized
|
|
158
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.ClientIdentifierNotValid:
|
|
159
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.MalformedPacket:
|
|
160
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.UnsupportedProtocolVersion:
|
|
161
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.BadAuthenticationMethod:
|
|
162
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.TopicNameInvalid:
|
|
163
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.PayloadFormatInvalid:
|
|
164
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.ImplementationSpecificError:
|
|
165
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.PacketTooLarge:
|
|
166
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.RetainNotSupported:
|
|
167
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.QosNotSupported:
|
|
168
|
+
return 400; // BadRequest
|
|
169
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.QuotaExceeded:
|
|
170
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.ConnectionRateExceeded:
|
|
171
|
+
return 429; // TooManyRequests
|
|
172
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.Banned:
|
|
173
|
+
return 403; // Forbidden
|
|
174
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.UseAnotherServer:
|
|
175
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.ServerMoved:
|
|
176
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.ServerUnavailable:
|
|
177
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.ServerBusy:
|
|
178
|
+
case mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.UnspecifiedError:
|
|
179
|
+
return 500; // InternalServerError
|
|
180
|
+
default:
|
|
181
|
+
logger_js_1.logger.warning(`Invalid MQTT connect return code: ${mqttConnectCode}.`);
|
|
182
|
+
return 500; // InternalServerError
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function getMqttConnectCodeFromStatusCode(statusCode, protocolVersion) {
|
|
187
|
+
if (protocolVersion === 4) {
|
|
188
|
+
switch (statusCode) {
|
|
189
|
+
case 400:
|
|
190
|
+
return mqttV311ConnectReturnCode_js_1.MqttV311ConnectReturnCode.BadUsernameOrPassword;
|
|
191
|
+
case 401:
|
|
192
|
+
return mqttV311ConnectReturnCode_js_1.MqttV311ConnectReturnCode.NotAuthorized;
|
|
193
|
+
case 500:
|
|
194
|
+
return mqttV311ConnectReturnCode_js_1.MqttV311ConnectReturnCode.ServerUnavailable;
|
|
195
|
+
default:
|
|
196
|
+
logger_js_1.logger.warning(`Unsupported HTTP Status Code: ${statusCode}.`);
|
|
197
|
+
return mqttV311ConnectReturnCode_js_1.MqttV311ConnectReturnCode.ServerUnavailable;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else if (protocolVersion === 5) {
|
|
201
|
+
switch (statusCode) {
|
|
202
|
+
case 400:
|
|
203
|
+
return mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.BadUserNameOrPassword;
|
|
204
|
+
case 401:
|
|
205
|
+
return mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.NotAuthorized;
|
|
206
|
+
case 500:
|
|
207
|
+
return mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.UnspecifiedError;
|
|
208
|
+
default:
|
|
209
|
+
logger_js_1.logger.warning(`Unsupported HTTP Status Code: ${statusCode}.`);
|
|
210
|
+
return mqttV500ConnectReasonCode_js_1.MqttV500ConnectReasonCode.UnspecifiedError;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
logger_js_1.logger.warning(`Invalid MQTT protocol version: ${protocolVersion}.`);
|
|
215
|
+
return mqttV311ConnectReturnCode_js_1.MqttV311ConnectReturnCode.UnacceptableProtocolVersion;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function handleConnectErrorResponse(connectRequest, response, code, detail) {
|
|
219
|
+
const isMqttReq = connectRequest.context.clientProtocol === "mqtt";
|
|
220
|
+
if (isMqttReq) {
|
|
221
|
+
const protocolVersion = connectRequest.mqtt.protocolVersion;
|
|
222
|
+
const mqttErrorResponse = {
|
|
223
|
+
mqtt: {
|
|
224
|
+
code: getMqttConnectCodeFromStatusCode(code, protocolVersion),
|
|
225
|
+
reason: detail,
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
response.statusCode = code;
|
|
229
|
+
response.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
230
|
+
response.end(JSON.stringify(mqttErrorResponse));
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
response.statusCode = code;
|
|
234
|
+
response.end(detail !== null && detail !== void 0 ? detail : "");
|
|
235
|
+
}
|
|
236
|
+
}
|
|
116
237
|
function isWebPubSubRequest(req) {
|
|
117
238
|
return utils.getHttpHeader(req, "ce-awpsversion") !== undefined;
|
|
118
239
|
}
|
|
240
|
+
function isMqttRequest(req) {
|
|
241
|
+
const subprotocol = utils.getHttpHeader(req, "ce-subprotocol");
|
|
242
|
+
const physicalConnectionId = utils.getHttpHeader(req, "ce-physicalConnectionId");
|
|
243
|
+
return (subprotocol !== undefined &&
|
|
244
|
+
subprotocol.toLowerCase().includes("mqtt") &&
|
|
245
|
+
physicalConnectionId !== undefined);
|
|
246
|
+
}
|
|
119
247
|
async function readUserEventRequest(request, origin) {
|
|
120
248
|
const contentTypeheader = utils.getHttpHeader(request, "content-type");
|
|
121
249
|
if (contentTypeheader === undefined) {
|
|
@@ -206,10 +334,13 @@ class CloudEventsDispatcher {
|
|
|
206
334
|
if ((hub === null || hub === void 0 ? void 0 : hub.toUpperCase()) !== this.hub.toUpperCase()) {
|
|
207
335
|
return false;
|
|
208
336
|
}
|
|
337
|
+
const isMqtt = isMqttRequest(request);
|
|
209
338
|
// No need to read body if handler is not specified
|
|
210
339
|
switch (eventType) {
|
|
211
340
|
case EventType.Connect:
|
|
212
341
|
if (!((_a = this.eventHandler) === null || _a === void 0 ? void 0 : _a.handleConnect)) {
|
|
342
|
+
if (isMqtt)
|
|
343
|
+
response.statusCode = 204;
|
|
213
344
|
response.end();
|
|
214
345
|
return true;
|
|
215
346
|
}
|
|
@@ -238,7 +369,9 @@ class CloudEventsDispatcher {
|
|
|
238
369
|
}
|
|
239
370
|
switch (eventType) {
|
|
240
371
|
case EventType.Connect: {
|
|
241
|
-
const connectRequest =
|
|
372
|
+
const connectRequest = isMqtt
|
|
373
|
+
? await readSystemEventRequest(request, origin)
|
|
374
|
+
: await readSystemEventRequest(request, origin);
|
|
242
375
|
// service passes out query property, assign it to queries
|
|
243
376
|
connectRequest.queries = connectRequest.query;
|
|
244
377
|
logger_js_1.logger.verbose(connectRequest);
|
|
@@ -256,7 +389,9 @@ class CloudEventsDispatcher {
|
|
|
256
389
|
case EventType.Disconnected: {
|
|
257
390
|
// for unblocking events, we responds to the service as early as possible
|
|
258
391
|
response.end();
|
|
259
|
-
const disconnectedRequest =
|
|
392
|
+
const disconnectedRequest = isMqtt
|
|
393
|
+
? await readSystemEventRequest(request, origin)
|
|
394
|
+
: await readSystemEventRequest(request, origin);
|
|
260
395
|
logger_js_1.logger.verbose(disconnectedRequest);
|
|
261
396
|
this.eventHandler.onDisconnected(disconnectedRequest);
|
|
262
397
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudEventsDispatcher.js","sourceRoot":"","sources":["../../src/cloudEventsDispatcher.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport * as utils from \"./utils.js\";\nimport { IncomingMessage, ServerResponse } from \"node:http\";\nimport { URL } from \"node:url\";\nimport { logger } from \"./logger.js\";\n\nimport type {\n ConnectRequest,\n ConnectResponse,\n ConnectedRequest,\n ConnectionContext,\n ConnectResponseHandler,\n DisconnectedRequest,\n UserEventRequest,\n UserEventResponseHandler,\n WebPubSubEventHandlerOptions,\n} from \"./cloudEventsProtocols.js\";\n\nenum EventType {\n Connect,\n Connected,\n Disconnected,\n UserEvent,\n}\n\nfunction getConnectResponseHandler(\n connectRequest: ConnectRequest,\n response: ServerResponse,\n): ConnectResponseHandler {\n const states: Record<string, any> = connectRequest.context.states;\n let modified = false;\n const handler = {\n setState(name: string, value: unknown): void {\n states[name] = value;\n modified = true;\n },\n success(res?: ConnectResponse): void {\n response.statusCode = 200;\n if (modified) {\n response.setHeader(\"ce-connectionState\", utils.toBase64JsonString(states));\n }\n if (res === undefined) {\n response.end();\n } else {\n response.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\n response.end(JSON.stringify(res));\n }\n },\n fail(code: 400 | 401 | 500, detail?: string): void {\n response.statusCode = code;\n response.end(detail ?? \"\");\n },\n };\n\n return handler;\n}\n\nfunction getUserEventResponseHandler(\n userRequest: UserEventRequest,\n response: ServerResponse,\n): UserEventResponseHandler {\n const states: Record<string, any> = userRequest.context.states;\n let modified = false;\n const handler = {\n setState(name: string, value: unknown): void {\n modified = true;\n states[name] = value;\n },\n success(data?: string | ArrayBuffer, dataType?: \"binary\" | \"text\" | \"json\"): void {\n response.statusCode = 200;\n if (modified) {\n response.setHeader(\"ce-connectionState\", utils.toBase64JsonString(states));\n }\n\n switch (dataType) {\n case \"json\":\n response.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\n break;\n case \"text\":\n response.setHeader(\"Content-Type\", \"text/plain; charset=utf-8\");\n break;\n default:\n response.setHeader(\"Content-Type\", \"application/octet-stream\");\n break;\n }\n response.end(data ?? \"\");\n },\n fail(code: 400 | 401 | 500, detail?: string): void {\n response.statusCode = code;\n response.end(detail ?? \"\");\n },\n };\n return handler;\n}\n\nfunction getContext(request: IncomingMessage, origin: string): ConnectionContext {\n const context = {\n signature: utils.getHttpHeader(request, \"ce-signature\"),\n userId: utils.getHttpHeader(request, \"ce-userid\"),\n hub: utils.getHttpHeader(request, \"ce-hub\")!,\n connectionId: utils.getHttpHeader(request, \"ce-connectionid\")!,\n eventName: utils.getHttpHeader(request, \"ce-eventname\")!,\n origin: origin,\n states: utils.fromBase64JsonString(utils.getHttpHeader(request, \"ce-connectionstate\")),\n };\n\n // TODO: validation\n return context;\n}\n\nfunction tryGetWebPubSubEvent(req: IncomingMessage): EventType | undefined {\n // check ce-type to see if it is a valid WebPubSub CloudEvent request\n const prefix = \"azure.webpubsub.\";\n const connect = \"azure.webpubsub.sys.connect\";\n const connected = \"azure.webpubsub.sys.connected\";\n const disconnectd = \"azure.webpubsub.sys.disconnected\";\n const userPrefix = \"azure.webpubsub.user.\";\n const type = utils.getHttpHeader(req, \"ce-type\");\n if (!type?.startsWith(prefix)) {\n return undefined;\n }\n if (type.startsWith(userPrefix)) {\n return EventType.UserEvent;\n }\n switch (type) {\n case connect:\n return EventType.Connect;\n case connected:\n return EventType.Connected;\n case disconnectd:\n return EventType.Disconnected;\n default:\n return undefined;\n }\n}\n\nfunction isWebPubSubRequest(req: IncomingMessage): boolean {\n return utils.getHttpHeader(req, \"ce-awpsversion\") !== undefined;\n}\n\nasync function readUserEventRequest(\n request: IncomingMessage,\n origin: string,\n): Promise<UserEventRequest | undefined> {\n const contentTypeheader = utils.getHttpHeader(request, \"content-type\");\n if (contentTypeheader === undefined) {\n return undefined;\n }\n\n const contentType = contentTypeheader.split(\";\")[0].trim();\n\n switch (contentType) {\n case \"application/octet-stream\":\n return {\n context: getContext(request, origin),\n data: await utils.readRequestBody(request),\n dataType: \"binary\",\n };\n case \"application/json\":\n return {\n context: getContext(request, origin),\n data: JSON.parse((await utils.readRequestBody(request)).toString()),\n dataType: \"json\",\n };\n case \"text/plain\":\n return {\n context: getContext(request, origin),\n data: (await utils.readRequestBody(request)).toString(),\n dataType: \"text\",\n };\n default:\n return undefined;\n }\n}\n\nasync function readSystemEventRequest<T extends { context: ConnectionContext }>(\n request: IncomingMessage,\n origin: string,\n): Promise<T> {\n const body = (await utils.readRequestBody(request)).toString();\n const parsedRequest = JSON.parse(body) as T;\n parsedRequest.context = getContext(request, origin);\n return parsedRequest;\n}\n\n/**\n * @internal\n */\nexport class CloudEventsDispatcher {\n private readonly _allowAll: boolean = true;\n private readonly _allowedOrigins: Array<string> = [];\n constructor(\n private hub: string,\n private eventHandler?: WebPubSubEventHandlerOptions,\n ) {\n if (Array.isArray(eventHandler)) {\n throw new Error(\"Unexpected WebPubSubEventHandlerOptions\");\n }\n if (eventHandler?.allowedEndpoints !== undefined) {\n this._allowedOrigins = eventHandler.allowedEndpoints.map((endpoint) =>\n new URL(endpoint).host.toLowerCase(),\n );\n this._allowAll = false;\n }\n }\n\n public handlePreflight(req: IncomingMessage, res: ServerResponse): boolean {\n if (!isWebPubSubRequest(req)) {\n return false;\n }\n const origin = utils.getHttpHeader(req, \"webhook-request-origin\");\n\n if (origin === undefined) {\n logger.warning(\"Expecting webhook-request-origin header.\");\n res.statusCode = 400;\n } else if (this._allowAll) {\n res.setHeader(\"WebHook-Allowed-Origin\", \"*\");\n } else {\n // service to do the check\n res.setHeader(\"WebHook-Allowed-Origin\", this._allowedOrigins);\n }\n\n res.end();\n return true;\n }\n\n public async handleRequest(request: IncomingMessage, response: ServerResponse): Promise<boolean> {\n if (!isWebPubSubRequest(request)) {\n return false;\n }\n\n // check if it is a valid WebPubSub cloud events\n const origin = utils.getHttpHeader(request, \"webhook-request-origin\");\n if (origin === undefined) {\n return false;\n }\n\n const eventType = tryGetWebPubSubEvent(request);\n if (eventType === undefined) {\n return false;\n }\n\n // check if hub matches\n const hub = utils.getHttpHeader(request, \"ce-hub\");\n if (hub?.toUpperCase() !== this.hub.toUpperCase()) {\n return false;\n }\n\n // No need to read body if handler is not specified\n switch (eventType) {\n case EventType.Connect:\n if (!this.eventHandler?.handleConnect) {\n response.end();\n return true;\n }\n break;\n case EventType.Connected:\n if (!this.eventHandler?.onConnected) {\n response.end();\n return true;\n }\n break;\n case EventType.Disconnected:\n if (!this.eventHandler?.onDisconnected) {\n response.end();\n return true;\n }\n break;\n case EventType.UserEvent:\n if (!this.eventHandler?.handleUserEvent) {\n response.end();\n return true;\n }\n break;\n default:\n logger.warning(`Unknown EventType ${eventType}`);\n return false;\n }\n\n switch (eventType) {\n case EventType.Connect: {\n const connectRequest = await readSystemEventRequest<ConnectRequest>(request, origin);\n // service passes out query property, assign it to queries\n connectRequest.queries = connectRequest.query;\n logger.verbose(connectRequest);\n\n this.eventHandler.handleConnect!(\n connectRequest,\n getConnectResponseHandler(connectRequest, response),\n );\n return true;\n }\n case EventType.Connected: {\n // for unblocking events, we responds to the service as early as possible\n response.end();\n const connectedRequest = await readSystemEventRequest<ConnectedRequest>(request, origin);\n logger.verbose(connectedRequest);\n this.eventHandler.onConnected!(connectedRequest);\n return true;\n }\n case EventType.Disconnected: {\n // for unblocking events, we responds to the service as early as possible\n response.end();\n const disconnectedRequest = await readSystemEventRequest<DisconnectedRequest>(\n request,\n origin,\n );\n logger.verbose(disconnectedRequest);\n this.eventHandler.onDisconnected!(disconnectedRequest);\n return true;\n }\n case EventType.UserEvent: {\n const userRequest = await readUserEventRequest(request, origin);\n if (userRequest === undefined) {\n logger.warning(\n `Unsupported content type ${utils.getHttpHeader(request, \"content-type\")}`,\n );\n return false;\n }\n logger.verbose(userRequest);\n this.eventHandler.handleUserEvent!(\n userRequest,\n getUserEventResponseHandler(userRequest, response),\n );\n return true;\n }\n default:\n logger.warning(`Unknown EventType ${eventType}`);\n return false;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cloudEventsDispatcher.js","sourceRoot":"","sources":["../../src/cloudEventsDispatcher.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport * as utils from \"./utils.js\";\nimport { IncomingMessage, ServerResponse } from \"node:http\";\nimport { URL } from \"node:url\";\nimport { logger } from \"./logger.js\";\n\nimport type {\n ConnectRequest,\n ConnectResponse,\n ConnectedRequest,\n ConnectionContext,\n ConnectResponseHandler,\n DisconnectedRequest,\n UserEventRequest,\n UserEventResponseHandler,\n WebPubSubEventHandlerOptions,\n MqttConnectRequest,\n MqttConnectErrorResponse,\n MqttConnectionContextProperties,\n ConnectErrorResponse,\n MqttDisconnectedRequest,\n} from \"./cloudEventsProtocols.js\";\nimport { MqttV311ConnectReturnCode } from \"./enum/MqttErrorCodes/mqttV311ConnectReturnCode.js\";\nimport { MqttV500ConnectReasonCode } from \"./enum/MqttErrorCodes/mqttV500ConnectReasonCode.js\";\n\nenum EventType {\n Connect,\n Connected,\n Disconnected,\n UserEvent,\n}\n\nfunction getConnectResponseHandler(\n connectRequest: ConnectRequest,\n response: ServerResponse,\n): ConnectResponseHandler {\n const states: Record<string, any> = connectRequest.context.states;\n let modified = false;\n const handler = {\n setState(name: string, value: unknown): void {\n states[name] = value;\n modified = true;\n },\n success(res?: ConnectResponse): void {\n if (modified) {\n response.setHeader(\"ce-connectionState\", utils.toBase64JsonString(states));\n }\n if (res === undefined) {\n response.statusCode = 204;\n response.end();\n } else {\n response.statusCode = 200;\n response.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\n response.end(JSON.stringify(res));\n }\n },\n fail(code: 400 | 401 | 500, detail?: string): void {\n handleConnectErrorResponse(connectRequest, response, code, detail);\n },\n failWith(res: ConnectErrorResponse | MqttConnectErrorResponse) {\n if (\"mqtt\" in res) {\n response.statusCode = getStatusCodeFromMqttConnectCode(res.mqtt.code);\n response.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\n response.end(JSON.stringify(res));\n } else {\n handleConnectErrorResponse(connectRequest, response, res.code, res.detail);\n }\n },\n };\n\n return handler;\n}\n\nfunction getUserEventResponseHandler(\n userRequest: UserEventRequest,\n response: ServerResponse,\n): UserEventResponseHandler {\n const states: Record<string, any> = userRequest.context.states;\n let modified = false;\n const handler = {\n setState(name: string, value: unknown): void {\n modified = true;\n states[name] = value;\n },\n success(data?: string | ArrayBuffer, dataType?: \"binary\" | \"text\" | \"json\"): void {\n response.statusCode = 200;\n if (modified) {\n response.setHeader(\"ce-connectionState\", utils.toBase64JsonString(states));\n }\n\n switch (dataType) {\n case \"json\":\n response.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\n break;\n case \"text\":\n response.setHeader(\"Content-Type\", \"text/plain; charset=utf-8\");\n break;\n default:\n response.setHeader(\"Content-Type\", \"application/octet-stream\");\n break;\n }\n response.end(data ?? \"\");\n },\n fail(code: 400 | 401 | 500, detail?: string): void {\n response.statusCode = code;\n response.end(detail ?? \"\");\n },\n };\n return handler;\n}\n\nfunction getContext(request: IncomingMessage, origin: string): ConnectionContext {\n const baseContext: ConnectionContext = {\n signature: utils.getHttpHeader(request, \"ce-signature\")!,\n userId: utils.getHttpHeader(request, \"ce-userid\"),\n hub: utils.getHttpHeader(request, \"ce-hub\")!,\n connectionId: utils.getHttpHeader(request, \"ce-connectionid\")!,\n eventName: utils.getHttpHeader(request, \"ce-eventname\")!,\n origin: origin,\n states: utils.fromBase64JsonString(utils.getHttpHeader(request, \"ce-connectionstate\")),\n clientProtocol: \"default\",\n };\n\n if (isMqttRequest(request)) {\n const mqttProperties: MqttConnectionContextProperties = {\n physicalConnectionId: utils.getHttpHeader(request, \"ce-physicalConnectionId\")!,\n sessionId: utils.getHttpHeader(request, \"ce-sessionId\"),\n };\n return {\n ...baseContext,\n clientProtocol: \"mqtt\",\n mqtt: mqttProperties,\n };\n } else {\n return baseContext;\n }\n}\n\nfunction tryGetWebPubSubEvent(req: IncomingMessage): EventType | undefined {\n // check ce-type to see if it is a valid WebPubSub CloudEvent request\n const prefix = \"azure.webpubsub.\";\n const connect = \"azure.webpubsub.sys.connect\";\n const connected = \"azure.webpubsub.sys.connected\";\n const disconnectd = \"azure.webpubsub.sys.disconnected\";\n const userPrefix = \"azure.webpubsub.user.\";\n const type = utils.getHttpHeader(req, \"ce-type\");\n if (!type?.startsWith(prefix)) {\n return undefined;\n }\n if (type.startsWith(userPrefix)) {\n return EventType.UserEvent;\n }\n switch (type) {\n case connect:\n return EventType.Connect;\n case connected:\n return EventType.Connected;\n case disconnectd:\n return EventType.Disconnected;\n default:\n return undefined;\n }\n}\n\nfunction getStatusCodeFromMqttConnectCode(\n mqttConnectCode: MqttV311ConnectReturnCode | MqttV500ConnectReasonCode,\n): number {\n if (mqttConnectCode < 0x80) {\n switch (mqttConnectCode) {\n case MqttV311ConnectReturnCode.UnacceptableProtocolVersion:\n case MqttV311ConnectReturnCode.IdentifierRejected:\n return 400; // BadRequest\n case MqttV311ConnectReturnCode.ServerUnavailable:\n return 503; // ServiceUnavailable\n case MqttV311ConnectReturnCode.BadUsernameOrPassword:\n case MqttV311ConnectReturnCode.NotAuthorized:\n return 401; // Unauthorized\n default:\n logger.warning(`Invalid MQTT connect return code: ${mqttConnectCode}.`);\n return 500; // InternalServerError\n }\n } else {\n switch (mqttConnectCode) {\n case MqttV500ConnectReasonCode.NotAuthorized:\n case MqttV500ConnectReasonCode.BadUserNameOrPassword:\n return 401; // Unauthorized\n case MqttV500ConnectReasonCode.ClientIdentifierNotValid:\n case MqttV500ConnectReasonCode.MalformedPacket:\n case MqttV500ConnectReasonCode.UnsupportedProtocolVersion:\n case MqttV500ConnectReasonCode.BadAuthenticationMethod:\n case MqttV500ConnectReasonCode.TopicNameInvalid:\n case MqttV500ConnectReasonCode.PayloadFormatInvalid:\n case MqttV500ConnectReasonCode.ImplementationSpecificError:\n case MqttV500ConnectReasonCode.PacketTooLarge:\n case MqttV500ConnectReasonCode.RetainNotSupported:\n case MqttV500ConnectReasonCode.QosNotSupported:\n return 400; // BadRequest\n case MqttV500ConnectReasonCode.QuotaExceeded:\n case MqttV500ConnectReasonCode.ConnectionRateExceeded:\n return 429; // TooManyRequests\n case MqttV500ConnectReasonCode.Banned:\n return 403; // Forbidden\n case MqttV500ConnectReasonCode.UseAnotherServer:\n case MqttV500ConnectReasonCode.ServerMoved:\n case MqttV500ConnectReasonCode.ServerUnavailable:\n case MqttV500ConnectReasonCode.ServerBusy:\n case MqttV500ConnectReasonCode.UnspecifiedError:\n return 500; // InternalServerError\n default:\n logger.warning(`Invalid MQTT connect return code: ${mqttConnectCode}.`);\n return 500; // InternalServerError\n }\n }\n}\n\nfunction getMqttConnectCodeFromStatusCode(\n statusCode: 400 | 401 | 500,\n protocolVersion: number,\n): MqttV311ConnectReturnCode | MqttV500ConnectReasonCode {\n if (protocolVersion === 4) {\n switch (statusCode) {\n case 400:\n return MqttV311ConnectReturnCode.BadUsernameOrPassword;\n case 401:\n return MqttV311ConnectReturnCode.NotAuthorized;\n case 500:\n return MqttV311ConnectReturnCode.ServerUnavailable;\n default:\n logger.warning(`Unsupported HTTP Status Code: ${statusCode}.`);\n return MqttV311ConnectReturnCode.ServerUnavailable;\n }\n } else if (protocolVersion === 5) {\n switch (statusCode) {\n case 400:\n return MqttV500ConnectReasonCode.BadUserNameOrPassword;\n case 401:\n return MqttV500ConnectReasonCode.NotAuthorized;\n case 500:\n return MqttV500ConnectReasonCode.UnspecifiedError;\n default:\n logger.warning(`Unsupported HTTP Status Code: ${statusCode}.`);\n return MqttV500ConnectReasonCode.UnspecifiedError;\n }\n } else {\n logger.warning(`Invalid MQTT protocol version: ${protocolVersion}.`);\n return MqttV311ConnectReturnCode.UnacceptableProtocolVersion;\n }\n}\n\nfunction handleConnectErrorResponse(\n connectRequest: ConnectRequest,\n response: ServerResponse,\n code: 400 | 401 | 500,\n detail?: string,\n): void {\n const isMqttReq = connectRequest.context.clientProtocol === \"mqtt\";\n if (isMqttReq) {\n const protocolVersion = (connectRequest as MqttConnectRequest).mqtt.protocolVersion;\n const mqttErrorResponse: MqttConnectErrorResponse = {\n mqtt: {\n code: getMqttConnectCodeFromStatusCode(code, protocolVersion),\n reason: detail,\n },\n };\n response.statusCode = code;\n response.setHeader(\"Content-Type\", \"application/json; charset=utf-8\");\n response.end(JSON.stringify(mqttErrorResponse));\n } else {\n response.statusCode = code;\n response.end(detail ?? \"\");\n }\n}\n\nfunction isWebPubSubRequest(req: IncomingMessage): boolean {\n return utils.getHttpHeader(req, \"ce-awpsversion\") !== undefined;\n}\n\nfunction isMqttRequest(req: IncomingMessage): boolean {\n const subprotocol = utils.getHttpHeader(req, \"ce-subprotocol\");\n const physicalConnectionId = utils.getHttpHeader(req, \"ce-physicalConnectionId\");\n return (\n subprotocol !== undefined &&\n subprotocol.toLowerCase().includes(\"mqtt\") &&\n physicalConnectionId !== undefined\n );\n}\n\nasync function readUserEventRequest(\n request: IncomingMessage,\n origin: string,\n): Promise<UserEventRequest | undefined> {\n const contentTypeheader = utils.getHttpHeader(request, \"content-type\");\n if (contentTypeheader === undefined) {\n return undefined;\n }\n\n const contentType = contentTypeheader.split(\";\")[0].trim();\n\n switch (contentType) {\n case \"application/octet-stream\":\n return {\n context: getContext(request, origin),\n data: await utils.readRequestBody(request),\n dataType: \"binary\",\n };\n case \"application/json\":\n return {\n context: getContext(request, origin),\n data: JSON.parse((await utils.readRequestBody(request)).toString()),\n dataType: \"json\",\n };\n case \"text/plain\":\n return {\n context: getContext(request, origin),\n data: (await utils.readRequestBody(request)).toString(),\n dataType: \"text\",\n };\n default:\n return undefined;\n }\n}\n\nasync function readSystemEventRequest<T extends { context: ConnectionContext }>(\n request: IncomingMessage,\n origin: string,\n): Promise<T> {\n const body = (await utils.readRequestBody(request)).toString();\n const parsedRequest = JSON.parse(body) as T;\n parsedRequest.context = getContext(request, origin);\n return parsedRequest;\n}\n\n/**\n * @internal\n */\nexport class CloudEventsDispatcher {\n private readonly _allowAll: boolean = true;\n private readonly _allowedOrigins: Array<string> = [];\n constructor(\n private hub: string,\n private eventHandler?: WebPubSubEventHandlerOptions,\n ) {\n if (Array.isArray(eventHandler)) {\n throw new Error(\"Unexpected WebPubSubEventHandlerOptions\");\n }\n if (eventHandler?.allowedEndpoints !== undefined) {\n this._allowedOrigins = eventHandler.allowedEndpoints.map((endpoint) =>\n new URL(endpoint).host.toLowerCase(),\n );\n this._allowAll = false;\n }\n }\n\n public handlePreflight(req: IncomingMessage, res: ServerResponse): boolean {\n if (!isWebPubSubRequest(req)) {\n return false;\n }\n const origin = utils.getHttpHeader(req, \"webhook-request-origin\");\n\n if (origin === undefined) {\n logger.warning(\"Expecting webhook-request-origin header.\");\n res.statusCode = 400;\n } else if (this._allowAll) {\n res.setHeader(\"WebHook-Allowed-Origin\", \"*\");\n } else {\n // service to do the check\n res.setHeader(\"WebHook-Allowed-Origin\", this._allowedOrigins);\n }\n\n res.end();\n return true;\n }\n\n public async handleRequest(request: IncomingMessage, response: ServerResponse): Promise<boolean> {\n if (!isWebPubSubRequest(request)) {\n return false;\n }\n\n // check if it is a valid WebPubSub cloud events\n const origin = utils.getHttpHeader(request, \"webhook-request-origin\");\n if (origin === undefined) {\n return false;\n }\n\n const eventType = tryGetWebPubSubEvent(request);\n if (eventType === undefined) {\n return false;\n }\n\n // check if hub matches\n const hub = utils.getHttpHeader(request, \"ce-hub\");\n if (hub?.toUpperCase() !== this.hub.toUpperCase()) {\n return false;\n }\n\n const isMqtt = isMqttRequest(request);\n // No need to read body if handler is not specified\n switch (eventType) {\n case EventType.Connect:\n if (!this.eventHandler?.handleConnect) {\n if (isMqtt) response.statusCode = 204;\n response.end();\n return true;\n }\n break;\n case EventType.Connected:\n if (!this.eventHandler?.onConnected) {\n response.end();\n return true;\n }\n break;\n case EventType.Disconnected:\n if (!this.eventHandler?.onDisconnected) {\n response.end();\n return true;\n }\n break;\n case EventType.UserEvent:\n if (!this.eventHandler?.handleUserEvent) {\n response.end();\n return true;\n }\n break;\n default:\n logger.warning(`Unknown EventType ${eventType}`);\n return false;\n }\n\n switch (eventType) {\n case EventType.Connect: {\n const connectRequest = isMqtt\n ? await readSystemEventRequest<MqttConnectRequest>(request, origin)\n : await readSystemEventRequest<ConnectRequest>(request, origin);\n // service passes out query property, assign it to queries\n connectRequest.queries = connectRequest.query;\n logger.verbose(connectRequest);\n this.eventHandler.handleConnect!(\n connectRequest,\n getConnectResponseHandler(connectRequest, response),\n );\n return true;\n }\n case EventType.Connected: {\n // for unblocking events, we responds to the service as early as possible\n response.end();\n const connectedRequest = await readSystemEventRequest<ConnectedRequest>(request, origin);\n logger.verbose(connectedRequest);\n this.eventHandler.onConnected!(connectedRequest);\n return true;\n }\n case EventType.Disconnected: {\n // for unblocking events, we responds to the service as early as possible\n response.end();\n const disconnectedRequest = isMqtt\n ? await readSystemEventRequest<MqttDisconnectedRequest>(request, origin)\n : await readSystemEventRequest<DisconnectedRequest>(request, origin);\n logger.verbose(disconnectedRequest);\n this.eventHandler.onDisconnected!(disconnectedRequest);\n return true;\n }\n case EventType.UserEvent: {\n const userRequest = await readUserEventRequest(request, origin);\n if (userRequest === undefined) {\n logger.warning(\n `Unsupported content type ${utils.getHttpHeader(request, \"content-type\")}`,\n );\n return false;\n }\n logger.verbose(userRequest);\n this.eventHandler.handleUserEvent!(\n userRequest,\n getUserEventResponseHandler(userRequest, response),\n );\n return true;\n }\n default:\n logger.warning(`Unknown EventType ${eventType}`);\n return false;\n }\n }\n}\n"]}
|