@azure/web-pubsub-express 1.0.0 → 1.0.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/CHANGELOG.md +7 -0
- package/dist/index.js +22 -15
- package/dist/index.js.map +1 -1
- package/dist-esm/samples-dev/server.js +1 -1
- package/dist-esm/samples-dev/server.js.map +1 -1
- package/dist-esm/src/cloudEventsDispatcher.js +7 -11
- package/dist-esm/src/cloudEventsDispatcher.js.map +1 -1
- package/dist-esm/src/cloudEventsProtocols.js.map +1 -1
- package/dist-esm/src/utils.js +15 -3
- package/dist-esm/src/utils.js.map +1 -1
- package/dist-esm/test/connect.spec.js +8 -8
- package/dist-esm/test/connect.spec.js.map +1 -1
- package/dist-esm/test/connected.spec.js +1 -1
- package/dist-esm/test/connected.spec.js.map +1 -1
- package/dist-esm/test/ctor.spec.js +1 -1
- package/dist-esm/test/ctor.spec.js.map +1 -1
- package/dist-esm/test/disconnected.spec.js +1 -1
- package/dist-esm/test/disconnected.spec.js.map +1 -1
- package/dist-esm/test/user.spec.js +80 -9
- package/dist-esm/test/user.spec.js.map +1 -1
- package/dist-esm/test/validate.spec.js +2 -2
- package/dist-esm/test/validate.spec.js.map +1 -1
- package/package.json +7 -19
- package/types/web-pubsub-express.d.ts +15 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
## 1.0.1 (2022-01-11)
|
|
4
|
+
|
|
5
|
+
### Bugs Fixed
|
|
6
|
+
|
|
7
|
+
- Fix the `data` definition for `UserEventRequest` when `dataType` is `json`. When `dataType` is `json`, `data` is the JSON parsed result from request body, so the type of `data` depends on the user scenario.
|
|
8
|
+
- Fix the CloudEvents parsing issue that now `data` also can be `boolean` or `number`.
|
|
9
|
+
|
|
3
10
|
## 1.0.0 (2021-11-11)
|
|
4
11
|
|
|
5
12
|
No changes.
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var cloudevents = require('cloudevents');
|
|
6
5
|
var url = require('url');
|
|
7
6
|
var logger$1 = require('@azure/logger');
|
|
7
|
+
var cloudevents = require('cloudevents');
|
|
8
8
|
|
|
9
9
|
// Copyright (c) Microsoft Corporation.
|
|
10
10
|
/**
|
|
@@ -15,7 +15,6 @@ var logger$1 = require('@azure/logger');
|
|
|
15
15
|
const logger = logger$1.createClientLogger("web-pubsub-express");
|
|
16
16
|
|
|
17
17
|
// Copyright (c) Microsoft Corporation.
|
|
18
|
-
// Licensed under the MIT license.
|
|
19
18
|
function isJsonObject(obj) {
|
|
20
19
|
return obj && typeof obj === "object" && !Array.isArray(obj);
|
|
21
20
|
}
|
|
@@ -49,7 +48,7 @@ function getHttpHeader(req, key) {
|
|
|
49
48
|
async function convertHttpToEvent(request) {
|
|
50
49
|
const normalized = {
|
|
51
50
|
headers: {},
|
|
52
|
-
body: ""
|
|
51
|
+
body: "",
|
|
53
52
|
};
|
|
54
53
|
if (request.headers) {
|
|
55
54
|
for (const key in request.headers) {
|
|
@@ -61,8 +60,19 @@ async function convertHttpToEvent(request) {
|
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
|
-
normalized.body = await readRequestBody(request);
|
|
65
|
-
|
|
63
|
+
const body = (normalized.body = await readRequestBody(request));
|
|
64
|
+
const receivedEvent = cloudevents.HTTP.toEvent(normalized);
|
|
65
|
+
if (isJsonData(receivedEvent)) {
|
|
66
|
+
// CloudEvent JSONParser wrap string with quotes however it is not the case for numbers or booleans
|
|
67
|
+
// https://github.com/cloudevents/sdk-javascript/blob/main/src/parsers.ts#L29
|
|
68
|
+
// We workaround it here by rewrite the parsed data property
|
|
69
|
+
receivedEvent.data = JSON.parse(body);
|
|
70
|
+
}
|
|
71
|
+
return receivedEvent;
|
|
72
|
+
}
|
|
73
|
+
function isJsonData(event) {
|
|
74
|
+
var _a;
|
|
75
|
+
return Boolean((_a = event.datacontenttype) === null || _a === void 0 ? void 0 : _a.startsWith("application/json;"));
|
|
66
76
|
}
|
|
67
77
|
function readRequestBody(req) {
|
|
68
78
|
return new Promise(function (resolve, reject) {
|
|
@@ -114,7 +124,7 @@ function getConnectResponseHandler(connectRequest, response) {
|
|
|
114
124
|
fail(code, detail) {
|
|
115
125
|
response.statusCode = code;
|
|
116
126
|
response.end(detail !== null && detail !== void 0 ? detail : "");
|
|
117
|
-
}
|
|
127
|
+
},
|
|
118
128
|
};
|
|
119
129
|
return handler;
|
|
120
130
|
}
|
|
@@ -147,7 +157,7 @@ function getUserEventResponseHandler(userRequest, response) {
|
|
|
147
157
|
fail(code, detail) {
|
|
148
158
|
response.statusCode = code;
|
|
149
159
|
response.end(detail !== null && detail !== void 0 ? detail : "");
|
|
150
|
-
}
|
|
160
|
+
},
|
|
151
161
|
};
|
|
152
162
|
return handler;
|
|
153
163
|
}
|
|
@@ -159,7 +169,7 @@ function getContext(ce, origin) {
|
|
|
159
169
|
connectionId: ce["connectionid"],
|
|
160
170
|
eventName: ce["eventname"],
|
|
161
171
|
origin: origin,
|
|
162
|
-
states: fromBase64JsonString(ce["connectionstate"])
|
|
172
|
+
states: fromBase64JsonString(ce["connectionstate"]),
|
|
163
173
|
};
|
|
164
174
|
// TODO: validation
|
|
165
175
|
return context;
|
|
@@ -230,7 +240,7 @@ class CloudEventsDispatcher {
|
|
|
230
240
|
return true;
|
|
231
241
|
}
|
|
232
242
|
async handleRequest(request, response) {
|
|
233
|
-
var _a, _b, _c, _d
|
|
243
|
+
var _a, _b, _c, _d;
|
|
234
244
|
if (!isWebPubSubRequest(request)) {
|
|
235
245
|
return false;
|
|
236
246
|
}
|
|
@@ -278,8 +288,7 @@ class CloudEventsDispatcher {
|
|
|
278
288
|
logger.warning(`Unknown EventType ${eventType}`);
|
|
279
289
|
return false;
|
|
280
290
|
}
|
|
281
|
-
const
|
|
282
|
-
const receivedEvent = cloudevents.HTTP.toEvent(eventRequest);
|
|
291
|
+
const receivedEvent = await convertHttpToEvent(request);
|
|
283
292
|
logger.verbose(receivedEvent);
|
|
284
293
|
switch (eventType) {
|
|
285
294
|
case EventType.Connect: {
|
|
@@ -310,16 +319,14 @@ class CloudEventsDispatcher {
|
|
|
310
319
|
userRequest = {
|
|
311
320
|
context: getContext(receivedEvent, origin),
|
|
312
321
|
data: Buffer.from(receivedEvent.data_base64, "base64"),
|
|
313
|
-
dataType: "binary"
|
|
322
|
+
dataType: "binary",
|
|
314
323
|
};
|
|
315
324
|
}
|
|
316
325
|
else if (receivedEvent.data !== undefined) {
|
|
317
326
|
userRequest = {
|
|
318
327
|
context: getContext(receivedEvent, origin),
|
|
319
328
|
data: receivedEvent.data,
|
|
320
|
-
dataType: (
|
|
321
|
-
? "json"
|
|
322
|
-
: "text"
|
|
329
|
+
dataType: isJsonData(receivedEvent) ? "json" : "text",
|
|
323
330
|
};
|
|
324
331
|
}
|
|
325
332
|
else {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/logger.ts","../src/utils.ts","../src/cloudEventsDispatcher.ts","../src/webPubSubEventHandler.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { createClientLogger } from \"@azure/logger\";\n\n/**\n * The \\@azure/logger configuration for this package.\n *\n * @internal\n */\nexport const logger = createClientLogger(\"web-pubsub-express\");\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { IncomingMessage } from \"http\";\nimport { Message } from \"cloudevents\";\n\nfunction isJsonObject(obj: any): boolean {\n return obj && typeof obj === \"object\" && !Array.isArray(obj);\n}\n\nexport function toBase64JsonString(obj: Record<string, any>): string {\n return Buffer.from(JSON.stringify(obj)).toString(\"base64\");\n}\n\nexport function fromBase64JsonString(base64String: string): Record<string, any> {\n if (base64String === undefined) {\n return {};\n }\n\n try {\n const buf = Buffer.from(base64String, \"base64\").toString();\n const parsed = JSON.parse(buf);\n return isJsonObject(parsed) ? parsed : {};\n } catch (e) {\n console.warn(\"Unexpected state format:\" + e);\n return {};\n }\n}\n\nexport function getHttpHeader(req: IncomingMessage, key: string): string | undefined {\n const value = req.headers[key];\n if (value === undefined) {\n return undefined;\n }\n\n if (typeof value === \"string\") {\n return value;\n }\n\n return value[0];\n}\n\nexport async function convertHttpToEvent(request: IncomingMessage): Promise<Message> {\n const normalized: Message = {\n headers: {},\n body: \"\"\n };\n if (request.headers) {\n for (const key in request.headers) {\n if (Object.prototype.hasOwnProperty.call(request.headers, key)) {\n const element = request.headers[key];\n if (element !== undefined) {\n normalized.headers[key.toLowerCase()] = element;\n }\n }\n }\n }\n\n normalized.body = await readRequestBody(request);\n return normalized;\n}\n\nexport function readRequestBody(req: IncomingMessage): Promise<string> {\n return new Promise(function(resolve, reject) {\n const chunks: any = [];\n req.on(\"data\", function(chunk) {\n chunks.push(chunk);\n });\n req.on(\"end\", function() {\n const buffer = Buffer.concat(chunks);\n resolve(buffer.toString());\n });\n // reject on request error\n req.on(\"error\", function(err) {\n // This is not a \"Second reject\", just a different sort of failure\n reject(err);\n });\n });\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { HTTP, CloudEvent } from \"cloudevents\";\nimport { IncomingMessage, ServerResponse } from \"http\";\nimport { URL } from \"url\";\nimport { logger } from \"./logger\";\nimport * as utils from \"./utils\";\n\nimport {\n ConnectRequest,\n ConnectResponse,\n UserEventRequest,\n DisconnectedRequest,\n ConnectedRequest,\n ConnectionContext,\n ConnectResponseHandler,\n UserEventResponseHandler,\n WebPubSubEventHandlerOptions\n} from \"./cloudEventsProtocols\";\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(ce: CloudEvent, origin: string): ConnectionContext {\n const context = {\n signature: ce[\"signature\"] as string,\n userId: ce[\"userid\"] as string,\n hub: ce[\"hub\"] as string,\n connectionId: ce[\"connectionid\"] as string,\n eventName: ce[\"eventname\"] as string,\n origin: origin,\n states: utils.fromBase64JsonString(ce[\"connectionstate\"] as string)\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\n/**\n * @internal\n */\nexport class CloudEventsDispatcher {\n private readonly _allowAll: boolean = true;\n private readonly _allowedOrigins: Array<string> = [];\n constructor(private hub: string, private eventHandler?: WebPubSubEventHandlerOptions) {\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\")?.toLowerCase();\n\n if (origin === undefined) {\n logger.warning(\"Expecting webhook-request-origin header.\");\n res.statusCode = 400;\n } else if (this._allowAll || this._allowedOrigins.indexOf(origin!) > -1) {\n res.setHeader(\"WebHook-Allowed-Origin\", origin!);\n } else {\n logger.warning(\"Origin does not match the allowed origins: \" + this._allowedOrigins);\n res.statusCode = 400;\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 !== this.hub) {\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 const eventRequest = await utils.convertHttpToEvent(request);\n const receivedEvent = HTTP.toEvent(eventRequest);\n\n logger.verbose(receivedEvent);\n\n switch (eventType) {\n case EventType.Connect: {\n const connectRequest = receivedEvent.data as ConnectRequest;\n connectRequest.context = getContext(receivedEvent, origin);\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 = receivedEvent.data as ConnectedRequest;\n connectedRequest.context = getContext(receivedEvent, origin);\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 = receivedEvent.data as DisconnectedRequest;\n disconnectedRequest.context = getContext(receivedEvent, origin);\n this.eventHandler.onDisconnected!(disconnectedRequest);\n return true;\n }\n case EventType.UserEvent: {\n let userRequest: UserEventRequest;\n if (receivedEvent.data_base64 !== undefined) {\n userRequest = {\n context: getContext(receivedEvent, origin),\n data: Buffer.from(receivedEvent.data_base64, \"base64\"),\n dataType: \"binary\"\n };\n } else if (receivedEvent.data !== undefined) {\n userRequest = {\n context: getContext(receivedEvent, origin),\n data: receivedEvent.data as string,\n dataType: receivedEvent.datacontenttype?.startsWith(\"application/json;\")\n ? \"json\"\n : \"text\"\n };\n } else {\n throw new Error(\"Unexpected data.\");\n }\n\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","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport express from \"express-serve-static-core\";\n\nimport { CloudEventsDispatcher } from \"./cloudEventsDispatcher\";\nimport { WebPubSubEventHandlerOptions } from \"./cloudEventsProtocols\";\n\n/**\n * The handler to handle incoming CloudEvents messages\n */\nexport class WebPubSubEventHandler {\n /**\n * The path this CloudEvents handler listens to\n */\n public readonly path: string;\n\n private _cloudEventsHandler: CloudEventsDispatcher;\n\n /**\n * Creates an instance of a WebPubSubEventHandler for handling incoming CloudEvents messages.\n *\n * Example usage:\n * ```ts\n * import express from \"express\";\n * import { WebPubSubEventHandler } from \"@azure/web-pubsub-express\";\n * const endpoint = \"https://xxxx.webpubsubdev.azure.com\"\n * const handler = new WebPubSubEventHandler('chat', {\n * handleConnect: (req, res) => {\n * console.log(JSON.stringify(req));\n * return {};\n * },\n * onConnected: req => {\n * console.log(JSON.stringify(req));\n * },\n * handleUserEvent: (req, res) => {\n * console.log(JSON.stringify(req));\n * res.success(\"Hey \" + req.data, req.dataType);\n * };\n * allowedEndpoints: [ endpoint ]\n * },\n * });\n * ```\n *\n * @param hub - The name of the hub to listen to\n * @param options - Options to configure the event handler\n */\n constructor(private hub: string, options?: WebPubSubEventHandlerOptions) {\n const path = (options?.path ?? `/api/webpubsub/hubs/${hub}/`).toLowerCase();\n this.path = path.endsWith(\"/\") ? path : path + \"/\";\n this._cloudEventsHandler = new CloudEventsDispatcher(this.hub, options);\n }\n\n /**\n * Get the middleware to process the CloudEvents requests\n */\n public getMiddleware(): express.RequestHandler {\n return async (\n req: express.Request,\n res: express.Response,\n next: express.NextFunction\n ): Promise<void> => {\n // Request originalUrl can contain query while baseUrl + path not\n let requestUrl = (req.baseUrl + req.path).toLowerCase();\n\n // normalize the Url\n requestUrl = requestUrl.endsWith(\"/\") ? requestUrl : requestUrl + \"/\";\n if (requestUrl.startsWith(this.path)) {\n if (req.method === \"OPTIONS\") {\n if (this._cloudEventsHandler.handlePreflight(req, res)) {\n return;\n }\n } else if (req.method === \"POST\") {\n try {\n if (await this._cloudEventsHandler.handleRequest(req, res)) {\n return;\n }\n } catch (err) {\n next(err);\n return;\n }\n }\n }\n\n next();\n };\n }\n}\n"],"names":["createClientLogger","utils.toBase64JsonString","utils.fromBase64JsonString","utils.getHttpHeader","URL","utils.convertHttpToEvent","HTTP"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/logger.ts","../src/utils.ts","../src/cloudEventsDispatcher.ts","../src/webPubSubEventHandler.ts"],"sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { createClientLogger } from \"@azure/logger\";\n\n/**\n * The \\@azure/logger configuration for this package.\n *\n * @internal\n */\nexport const logger = createClientLogger(\"web-pubsub-express\");\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { IncomingMessage } from \"http\";\nimport { CloudEvent, HTTP, Message } from \"cloudevents\";\n\nfunction isJsonObject(obj: any): boolean {\n return obj && typeof obj === \"object\" && !Array.isArray(obj);\n}\n\nexport function toBase64JsonString(obj: Record<string, any>): string {\n return Buffer.from(JSON.stringify(obj)).toString(\"base64\");\n}\n\nexport function fromBase64JsonString(base64String: string): Record<string, any> {\n if (base64String === undefined) {\n return {};\n }\n\n try {\n const buf = Buffer.from(base64String, \"base64\").toString();\n const parsed = JSON.parse(buf);\n return isJsonObject(parsed) ? parsed : {};\n } catch (e) {\n console.warn(\"Unexpected state format:\" + e);\n return {};\n }\n}\n\nexport function getHttpHeader(req: IncomingMessage, key: string): string | undefined {\n const value = req.headers[key];\n if (value === undefined) {\n return undefined;\n }\n\n if (typeof value === \"string\") {\n return value;\n }\n\n return value[0];\n}\n\nexport async function convertHttpToEvent(request: IncomingMessage): Promise<CloudEvent> {\n const normalized: Message = {\n headers: {},\n body: \"\",\n };\n if (request.headers) {\n for (const key in request.headers) {\n if (Object.prototype.hasOwnProperty.call(request.headers, key)) {\n const element = request.headers[key];\n if (element !== undefined) {\n normalized.headers[key.toLowerCase()] = element;\n }\n }\n }\n }\n\n const body = (normalized.body = await readRequestBody(request));\n const receivedEvent = HTTP.toEvent(normalized);\n if (isJsonData(receivedEvent)) {\n // CloudEvent JSONParser wrap string with quotes however it is not the case for numbers or booleans\n // https://github.com/cloudevents/sdk-javascript/blob/main/src/parsers.ts#L29\n // We workaround it here by rewrite the parsed data property\n receivedEvent.data = JSON.parse(body);\n }\n\n return receivedEvent;\n}\n\nexport function isJsonData(event: CloudEvent): boolean {\n return Boolean(event.datacontenttype?.startsWith(\"application/json;\"));\n}\n\nexport function readRequestBody(req: IncomingMessage): Promise<string> {\n return new Promise(function (resolve, reject) {\n const chunks: any = [];\n req.on(\"data\", function (chunk) {\n chunks.push(chunk);\n });\n req.on(\"end\", function () {\n const buffer = Buffer.concat(chunks);\n resolve(buffer.toString());\n });\n // reject on request error\n req.on(\"error\", function (err) {\n // This is not a \"Second reject\", just a different sort of failure\n reject(err);\n });\n });\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { CloudEvent } from \"cloudevents\";\nimport { IncomingMessage, ServerResponse } from \"http\";\nimport { URL } from \"url\";\nimport { logger } from \"./logger\";\nimport * as utils from \"./utils\";\n\nimport {\n ConnectRequest,\n ConnectResponse,\n UserEventRequest,\n DisconnectedRequest,\n ConnectedRequest,\n ConnectionContext,\n ConnectResponseHandler,\n UserEventResponseHandler,\n WebPubSubEventHandlerOptions,\n} from \"./cloudEventsProtocols\";\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(ce: CloudEvent, origin: string): ConnectionContext {\n const context = {\n signature: ce[\"signature\"] as string,\n userId: ce[\"userid\"] as string,\n hub: ce[\"hub\"] as string,\n connectionId: ce[\"connectionid\"] as string,\n eventName: ce[\"eventname\"] as string,\n origin: origin,\n states: utils.fromBase64JsonString(ce[\"connectionstate\"] as string),\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\n/**\n * @internal\n */\nexport class CloudEventsDispatcher {\n private readonly _allowAll: boolean = true;\n private readonly _allowedOrigins: Array<string> = [];\n constructor(private hub: string, private eventHandler?: WebPubSubEventHandlerOptions) {\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\")?.toLowerCase();\n\n if (origin === undefined) {\n logger.warning(\"Expecting webhook-request-origin header.\");\n res.statusCode = 400;\n } else if (this._allowAll || this._allowedOrigins.indexOf(origin!) > -1) {\n res.setHeader(\"WebHook-Allowed-Origin\", origin!);\n } else {\n logger.warning(\"Origin does not match the allowed origins: \" + this._allowedOrigins);\n res.statusCode = 400;\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 !== this.hub) {\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 const receivedEvent = await utils.convertHttpToEvent(request);\n logger.verbose(receivedEvent);\n\n switch (eventType) {\n case EventType.Connect: {\n const connectRequest = receivedEvent.data as ConnectRequest;\n connectRequest.context = getContext(receivedEvent, origin);\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 = receivedEvent.data as ConnectedRequest;\n connectedRequest.context = getContext(receivedEvent, origin);\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 = receivedEvent.data as DisconnectedRequest;\n disconnectedRequest.context = getContext(receivedEvent, origin);\n this.eventHandler.onDisconnected!(disconnectedRequest);\n return true;\n }\n case EventType.UserEvent: {\n let userRequest: UserEventRequest;\n if (receivedEvent.data_base64 !== undefined) {\n userRequest = {\n context: getContext(receivedEvent, origin),\n data: Buffer.from(receivedEvent.data_base64, \"base64\"),\n dataType: \"binary\",\n };\n } else if (receivedEvent.data !== undefined) {\n userRequest = {\n context: getContext(receivedEvent, origin),\n data: receivedEvent.data as string,\n dataType: utils.isJsonData(receivedEvent) ? \"json\" : \"text\",\n };\n } else {\n throw new Error(\"Unexpected data.\");\n }\n\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","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport express from \"express-serve-static-core\";\n\nimport { CloudEventsDispatcher } from \"./cloudEventsDispatcher\";\nimport { WebPubSubEventHandlerOptions } from \"./cloudEventsProtocols\";\n\n/**\n * The handler to handle incoming CloudEvents messages\n */\nexport class WebPubSubEventHandler {\n /**\n * The path this CloudEvents handler listens to\n */\n public readonly path: string;\n\n private _cloudEventsHandler: CloudEventsDispatcher;\n\n /**\n * Creates an instance of a WebPubSubEventHandler for handling incoming CloudEvents messages.\n *\n * Example usage:\n * ```ts\n * import express from \"express\";\n * import { WebPubSubEventHandler } from \"@azure/web-pubsub-express\";\n * const endpoint = \"https://xxxx.webpubsubdev.azure.com\"\n * const handler = new WebPubSubEventHandler('chat', {\n * handleConnect: (req, res) => {\n * console.log(JSON.stringify(req));\n * return {};\n * },\n * onConnected: req => {\n * console.log(JSON.stringify(req));\n * },\n * handleUserEvent: (req, res) => {\n * console.log(JSON.stringify(req));\n * res.success(\"Hey \" + req.data, req.dataType);\n * };\n * allowedEndpoints: [ endpoint ]\n * },\n * });\n * ```\n *\n * @param hub - The name of the hub to listen to\n * @param options - Options to configure the event handler\n */\n constructor(private hub: string, options?: WebPubSubEventHandlerOptions) {\n const path = (options?.path ?? `/api/webpubsub/hubs/${hub}/`).toLowerCase();\n this.path = path.endsWith(\"/\") ? path : path + \"/\";\n this._cloudEventsHandler = new CloudEventsDispatcher(this.hub, options);\n }\n\n /**\n * Get the middleware to process the CloudEvents requests\n */\n public getMiddleware(): express.RequestHandler {\n return async (\n req: express.Request,\n res: express.Response,\n next: express.NextFunction\n ): Promise<void> => {\n // Request originalUrl can contain query while baseUrl + path not\n let requestUrl = (req.baseUrl + req.path).toLowerCase();\n\n // normalize the Url\n requestUrl = requestUrl.endsWith(\"/\") ? requestUrl : requestUrl + \"/\";\n if (requestUrl.startsWith(this.path)) {\n if (req.method === \"OPTIONS\") {\n if (this._cloudEventsHandler.handlePreflight(req, res)) {\n return;\n }\n } else if (req.method === \"POST\") {\n try {\n if (await this._cloudEventsHandler.handleRequest(req, res)) {\n return;\n }\n } catch (err) {\n next(err);\n return;\n }\n }\n }\n\n next();\n };\n }\n}\n"],"names":["createClientLogger","HTTP","utils.toBase64JsonString","utils.fromBase64JsonString","utils.getHttpHeader","URL","utils.convertHttpToEvent","utils.isJsonData"],"mappings":"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"}
|
|
@@ -24,7 +24,7 @@ const handler = new WebPubSubEventHandler("chat", {
|
|
|
24
24
|
res.setState("calledTime", calledTime);
|
|
25
25
|
res.success("Hello", "text");
|
|
26
26
|
},
|
|
27
|
-
allowedEndpoints: ["https://xxx.webpubsub.azure.com"]
|
|
27
|
+
allowedEndpoints: ["https://xxx.webpubsub.azure.com"],
|
|
28
28
|
});
|
|
29
29
|
const app = express();
|
|
30
30
|
app.use(handler.getMiddleware());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../samples-dev/server.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,MAAM,OAAO,GAAG,IAAI,qBAAqB,CAAC,MAAM,EAAE;IAChD,aAAa,CAAC,GAAG,EAAE,GAAG;QACpB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjB,+FAA+F;QAC/F,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC9B,GAAG,CAAC,OAAO,EAAE,CAAC;QACd,UAAU;QACV,iBAAiB;IACnB,CAAC;IACD,WAAW,CAAC,gBAAgB;QAC1B,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAChC,CAAC;IACD,eAAe,CAAC,GAAG,EAAE,GAAG;QACtB,IAAI,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxB,kCAAkC;QAClC,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QACvC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC/B,CAAC;IACD,gBAAgB,EAAE,CAAC,iCAAiC,CAAC;CACtD,CAAC,CAAC;AAEH,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;AAEtB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;AAEjC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,CACpB,OAAO,CAAC,GAAG,CAAC,0DAA0D,OAAO,CAAC,IAAI,EAAE,CAAC,CACtF,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * @summary Demonstrates handling Web PubSub CloudEvents with Express\n */\n\nimport { WebPubSubEventHandler } from \"@azure/web-pubsub-express\";\nimport express from \"express\";\n\nconst handler = new WebPubSubEventHandler(\"chat\", {\n handleConnect(req, res) {\n console.log(req);\n // You can set the state for the connection, it lasts throughout the lifetime of the connection\n res.setState(\"calledTime\", 1);\n res.success();\n // or fail\n // res.fail(401);\n },\n onConnected(connectedRequest) {\n console.log(connectedRequest);\n },\n handleUserEvent(req, res) {\n var calledTime = req.context.states.calledTime++;\n console.log(calledTime);\n // You can also set the state here\n res.setState(\"calledTime\", calledTime);\n res.success(\"Hello\", \"text\");\n },\n allowedEndpoints: [\"https://xxx.webpubsub.azure.com\"]
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../samples-dev/server.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,MAAM,OAAO,GAAG,IAAI,qBAAqB,CAAC,MAAM,EAAE;IAChD,aAAa,CAAC,GAAG,EAAE,GAAG;QACpB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjB,+FAA+F;QAC/F,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC9B,GAAG,CAAC,OAAO,EAAE,CAAC;QACd,UAAU;QACV,iBAAiB;IACnB,CAAC;IACD,WAAW,CAAC,gBAAgB;QAC1B,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAChC,CAAC;IACD,eAAe,CAAC,GAAG,EAAE,GAAG;QACtB,IAAI,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxB,kCAAkC;QAClC,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QACvC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC/B,CAAC;IACD,gBAAgB,EAAE,CAAC,iCAAiC,CAAC;CACtD,CAAC,CAAC;AAEH,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;AAEtB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;AAEjC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,CACpB,OAAO,CAAC,GAAG,CAAC,0DAA0D,OAAO,CAAC,IAAI,EAAE,CAAC,CACtF,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * @summary Demonstrates handling Web PubSub CloudEvents with Express\n */\n\nimport { WebPubSubEventHandler } from \"@azure/web-pubsub-express\";\nimport express from \"express\";\n\nconst handler = new WebPubSubEventHandler(\"chat\", {\n handleConnect(req, res) {\n console.log(req);\n // You can set the state for the connection, it lasts throughout the lifetime of the connection\n res.setState(\"calledTime\", 1);\n res.success();\n // or fail\n // res.fail(401);\n },\n onConnected(connectedRequest) {\n console.log(connectedRequest);\n },\n handleUserEvent(req, res) {\n var calledTime = req.context.states.calledTime++;\n console.log(calledTime);\n // You can also set the state here\n res.setState(\"calledTime\", calledTime);\n res.success(\"Hello\", \"text\");\n },\n allowedEndpoints: [\"https://xxx.webpubsub.azure.com\"],\n});\n\nconst app = express();\n\napp.use(handler.getMiddleware());\n\napp.listen(3000, () =>\n console.log(`Azure WebPubSub Upstream ready at http://localhost:3000${handler.path}`)\n);\n"]}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
-
import { HTTP } from "cloudevents";
|
|
4
3
|
import { URL } from "url";
|
|
5
4
|
import { logger } from "./logger";
|
|
6
5
|
import * as utils from "./utils";
|
|
@@ -35,7 +34,7 @@ function getConnectResponseHandler(connectRequest, response) {
|
|
|
35
34
|
fail(code, detail) {
|
|
36
35
|
response.statusCode = code;
|
|
37
36
|
response.end(detail !== null && detail !== void 0 ? detail : "");
|
|
38
|
-
}
|
|
37
|
+
},
|
|
39
38
|
};
|
|
40
39
|
return handler;
|
|
41
40
|
}
|
|
@@ -68,7 +67,7 @@ function getUserEventResponseHandler(userRequest, response) {
|
|
|
68
67
|
fail(code, detail) {
|
|
69
68
|
response.statusCode = code;
|
|
70
69
|
response.end(detail !== null && detail !== void 0 ? detail : "");
|
|
71
|
-
}
|
|
70
|
+
},
|
|
72
71
|
};
|
|
73
72
|
return handler;
|
|
74
73
|
}
|
|
@@ -80,7 +79,7 @@ function getContext(ce, origin) {
|
|
|
80
79
|
connectionId: ce["connectionid"],
|
|
81
80
|
eventName: ce["eventname"],
|
|
82
81
|
origin: origin,
|
|
83
|
-
states: utils.fromBase64JsonString(ce["connectionstate"])
|
|
82
|
+
states: utils.fromBase64JsonString(ce["connectionstate"]),
|
|
84
83
|
};
|
|
85
84
|
// TODO: validation
|
|
86
85
|
return context;
|
|
@@ -151,7 +150,7 @@ export class CloudEventsDispatcher {
|
|
|
151
150
|
return true;
|
|
152
151
|
}
|
|
153
152
|
async handleRequest(request, response) {
|
|
154
|
-
var _a, _b, _c, _d
|
|
153
|
+
var _a, _b, _c, _d;
|
|
155
154
|
if (!isWebPubSubRequest(request)) {
|
|
156
155
|
return false;
|
|
157
156
|
}
|
|
@@ -199,8 +198,7 @@ export class CloudEventsDispatcher {
|
|
|
199
198
|
logger.warning(`Unknown EventType ${eventType}`);
|
|
200
199
|
return false;
|
|
201
200
|
}
|
|
202
|
-
const
|
|
203
|
-
const receivedEvent = HTTP.toEvent(eventRequest);
|
|
201
|
+
const receivedEvent = await utils.convertHttpToEvent(request);
|
|
204
202
|
logger.verbose(receivedEvent);
|
|
205
203
|
switch (eventType) {
|
|
206
204
|
case EventType.Connect: {
|
|
@@ -231,16 +229,14 @@ export class CloudEventsDispatcher {
|
|
|
231
229
|
userRequest = {
|
|
232
230
|
context: getContext(receivedEvent, origin),
|
|
233
231
|
data: Buffer.from(receivedEvent.data_base64, "base64"),
|
|
234
|
-
dataType: "binary"
|
|
232
|
+
dataType: "binary",
|
|
235
233
|
};
|
|
236
234
|
}
|
|
237
235
|
else if (receivedEvent.data !== undefined) {
|
|
238
236
|
userRequest = {
|
|
239
237
|
context: getContext(receivedEvent, origin),
|
|
240
238
|
data: receivedEvent.data,
|
|
241
|
-
dataType: (
|
|
242
|
-
? "json"
|
|
243
|
-
: "text"
|
|
239
|
+
dataType: utils.isJsonData(receivedEvent) ? "json" : "text",
|
|
244
240
|
};
|
|
245
241
|
}
|
|
246
242
|
else {
|
|
@@ -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 { HTTP, CloudEvent } from \"cloudevents\";\nimport { IncomingMessage, ServerResponse } from \"http\";\nimport { URL } from \"url\";\nimport { logger } from \"./logger\";\nimport * as utils from \"./utils\";\n\nimport {\n ConnectRequest,\n ConnectResponse,\n UserEventRequest,\n DisconnectedRequest,\n ConnectedRequest,\n ConnectionContext,\n ConnectResponseHandler,\n UserEventResponseHandler,\n WebPubSubEventHandlerOptions\n} from \"./cloudEventsProtocols\";\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(ce: CloudEvent, origin: string): ConnectionContext {\n const context = {\n signature: ce[\"signature\"] as string,\n userId: ce[\"userid\"] as string,\n hub: ce[\"hub\"] as string,\n connectionId: ce[\"connectionid\"] as string,\n eventName: ce[\"eventname\"] as string,\n origin: origin,\n states: utils.fromBase64JsonString(ce[\"connectionstate\"] as string)\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\n/**\n * @internal\n */\nexport class CloudEventsDispatcher {\n private readonly _allowAll: boolean = true;\n private readonly _allowedOrigins: Array<string> = [];\n constructor(private hub: string, private eventHandler?: WebPubSubEventHandlerOptions) {\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\")?.toLowerCase();\n\n if (origin === undefined) {\n logger.warning(\"Expecting webhook-request-origin header.\");\n res.statusCode = 400;\n } else if (this._allowAll || this._allowedOrigins.indexOf(origin!) > -1) {\n res.setHeader(\"WebHook-Allowed-Origin\", origin!);\n } else {\n logger.warning(\"Origin does not match the allowed origins: \" + this._allowedOrigins);\n res.statusCode = 400;\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 !== this.hub) {\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 const eventRequest = await utils.convertHttpToEvent(request);\n const receivedEvent = HTTP.toEvent(eventRequest);\n\n logger.verbose(receivedEvent);\n\n switch (eventType) {\n case EventType.Connect: {\n const connectRequest = receivedEvent.data as ConnectRequest;\n connectRequest.context = getContext(receivedEvent, origin);\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 = receivedEvent.data as ConnectedRequest;\n connectedRequest.context = getContext(receivedEvent, origin);\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 = receivedEvent.data as DisconnectedRequest;\n disconnectedRequest.context = getContext(receivedEvent, origin);\n this.eventHandler.onDisconnected!(disconnectedRequest);\n return true;\n }\n case EventType.UserEvent: {\n let userRequest: UserEventRequest;\n if (receivedEvent.data_base64 !== undefined) {\n userRequest = {\n context: getContext(receivedEvent, origin),\n data: Buffer.from(receivedEvent.data_base64, \"base64\"),\n dataType: \"binary\"\n };\n } else if (receivedEvent.data !== undefined) {\n userRequest = {\n context: getContext(receivedEvent, origin),\n data: receivedEvent.data as string,\n dataType: receivedEvent.datacontenttype?.startsWith(\"application/json;\")\n ? \"json\"\n : \"text\"\n };\n } else {\n throw new Error(\"Unexpected data.\");\n }\n\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 { CloudEvent } from \"cloudevents\";\nimport { IncomingMessage, ServerResponse } from \"http\";\nimport { URL } from \"url\";\nimport { logger } from \"./logger\";\nimport * as utils from \"./utils\";\n\nimport {\n ConnectRequest,\n ConnectResponse,\n UserEventRequest,\n DisconnectedRequest,\n ConnectedRequest,\n ConnectionContext,\n ConnectResponseHandler,\n UserEventResponseHandler,\n WebPubSubEventHandlerOptions,\n} from \"./cloudEventsProtocols\";\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(ce: CloudEvent, origin: string): ConnectionContext {\n const context = {\n signature: ce[\"signature\"] as string,\n userId: ce[\"userid\"] as string,\n hub: ce[\"hub\"] as string,\n connectionId: ce[\"connectionid\"] as string,\n eventName: ce[\"eventname\"] as string,\n origin: origin,\n states: utils.fromBase64JsonString(ce[\"connectionstate\"] as string),\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\n/**\n * @internal\n */\nexport class CloudEventsDispatcher {\n private readonly _allowAll: boolean = true;\n private readonly _allowedOrigins: Array<string> = [];\n constructor(private hub: string, private eventHandler?: WebPubSubEventHandlerOptions) {\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\")?.toLowerCase();\n\n if (origin === undefined) {\n logger.warning(\"Expecting webhook-request-origin header.\");\n res.statusCode = 400;\n } else if (this._allowAll || this._allowedOrigins.indexOf(origin!) > -1) {\n res.setHeader(\"WebHook-Allowed-Origin\", origin!);\n } else {\n logger.warning(\"Origin does not match the allowed origins: \" + this._allowedOrigins);\n res.statusCode = 400;\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 !== this.hub) {\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 const receivedEvent = await utils.convertHttpToEvent(request);\n logger.verbose(receivedEvent);\n\n switch (eventType) {\n case EventType.Connect: {\n const connectRequest = receivedEvent.data as ConnectRequest;\n connectRequest.context = getContext(receivedEvent, origin);\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 = receivedEvent.data as ConnectedRequest;\n connectedRequest.context = getContext(receivedEvent, origin);\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 = receivedEvent.data as DisconnectedRequest;\n disconnectedRequest.context = getContext(receivedEvent, origin);\n this.eventHandler.onDisconnected!(disconnectedRequest);\n return true;\n }\n case EventType.UserEvent: {\n let userRequest: UserEventRequest;\n if (receivedEvent.data_base64 !== undefined) {\n userRequest = {\n context: getContext(receivedEvent, origin),\n data: Buffer.from(receivedEvent.data_base64, \"base64\"),\n dataType: \"binary\",\n };\n } else if (receivedEvent.data !== undefined) {\n userRequest = {\n context: getContext(receivedEvent, origin),\n data: receivedEvent.data as string,\n dataType: utils.isJsonData(receivedEvent) ? \"json\" : \"text\",\n };\n } else {\n throw new Error(\"Unexpected data.\");\n }\n\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudEventsProtocols.js","sourceRoot":"","sources":["../../src/cloudEventsProtocols.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Response of the connect event.\n */\nexport interface ConnectResponse {\n /**\n * Set the groups the connection would like to join.\n */\n groups?: string[];\n /**\n * Set the roles the connection belongs to.\n */\n roles?: string[];\n /**\n * Set the userId for the connection.\n */\n userId?: string;\n /**\n * Set the subprotocol for the connection to complete WebSocket handshake.\n */\n subprotocol?: string;\n}\n\n/**\n * The connection context representing the client WebSocket connection.\n */\nexport interface ConnectionContext {\n /**\n * The hub the connection belongs to.\n */\n hub: string;\n /**\n * The Id of the connection.\n */\n connectionId: string;\n /**\n * The event name of this CloudEvents request.\n */\n eventName: string;\n /**\n * The origin this CloudEvents request comes from.\n */\n origin: string;\n /**\n * The user id of the connection.\n */\n userId?: string;\n /**\n * The subprotocol of this connection.\n */\n subprotocol?: string;\n /**\n * Get the additional states for the connection, such states are perserved throughout the lifetime of the connection.\n */\n states: Record<string, any>;\n}\n\n/**\n * Request for the connect event.\n */\nexport interface ConnectRequest {\n /**\n * The context of current CloudEvents request.\n */\n context: ConnectionContext;\n /**\n * The claims that the client WebSocket connection has when it connects.\n */\n claims?: Record<string, string[]>;\n /**\n * The queries that the client WebSocket connection has when it connects.\n */\n queries?: Record<string, string[]>;\n /**\n * The headers that the client WebSocket connection has when it connects.\n */\n headers?: Record<string, string[]>;\n /**\n * The subprotocols that the client WebSocket connection uses to do handshake.\n */\n subprotocols?: string[];\n /**\n * The client certificate info that the client WebSocket connection uses to connect.\n */\n clientCertificates?: Certificate[];\n}\n\n/**\n * The client certificate.\n */\nexport interface Certificate {\n /**\n * The thumbprint of the certificate.\n */\n thumbprint: string;\n}\n\n/**\n * Request for the connected event.\n */\nexport interface ConnectedRequest {\n /**\n * The context of current CloudEvents request.\n */\n context: ConnectionContext;\n}\n\n/**\n * Request for the user event.\n */\nexport type UserEventRequest =\n | {\n /**\n * The context of current CloudEvents request.\n */\n context: ConnectionContext;\n\n /**\n * The content data.\n */\n data: string;\n /**\n * The type of the data.\n */\n dataType: \"text\"
|
|
1
|
+
{"version":3,"file":"cloudEventsProtocols.js","sourceRoot":"","sources":["../../src/cloudEventsProtocols.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Response of the connect event.\n */\nexport interface ConnectResponse {\n /**\n * Set the groups the connection would like to join.\n */\n groups?: string[];\n /**\n * Set the roles the connection belongs to.\n */\n roles?: string[];\n /**\n * Set the userId for the connection.\n */\n userId?: string;\n /**\n * Set the subprotocol for the connection to complete WebSocket handshake.\n */\n subprotocol?: string;\n}\n\n/**\n * The connection context representing the client WebSocket connection.\n */\nexport interface ConnectionContext {\n /**\n * The hub the connection belongs to.\n */\n hub: string;\n /**\n * The Id of the connection.\n */\n connectionId: string;\n /**\n * The event name of this CloudEvents request.\n */\n eventName: string;\n /**\n * The origin this CloudEvents request comes from.\n */\n origin: string;\n /**\n * The user id of the connection.\n */\n userId?: string;\n /**\n * The subprotocol of this connection.\n */\n subprotocol?: string;\n /**\n * Get the additional states for the connection, such states are perserved throughout the lifetime of the connection.\n */\n states: Record<string, any>;\n}\n\n/**\n * Request for the connect event.\n */\nexport interface ConnectRequest {\n /**\n * The context of current CloudEvents request.\n */\n context: ConnectionContext;\n /**\n * The claims that the client WebSocket connection has when it connects.\n */\n claims?: Record<string, string[]>;\n /**\n * The queries that the client WebSocket connection has when it connects.\n */\n queries?: Record<string, string[]>;\n /**\n * The headers that the client WebSocket connection has when it connects.\n */\n headers?: Record<string, string[]>;\n /**\n * The subprotocols that the client WebSocket connection uses to do handshake.\n */\n subprotocols?: string[];\n /**\n * The client certificate info that the client WebSocket connection uses to connect.\n */\n clientCertificates?: Certificate[];\n}\n\n/**\n * The client certificate.\n */\nexport interface Certificate {\n /**\n * The thumbprint of the certificate.\n */\n thumbprint: string;\n}\n\n/**\n * Request for the connected event.\n */\nexport interface ConnectedRequest {\n /**\n * The context of current CloudEvents request.\n */\n context: ConnectionContext;\n}\n\n/**\n * Request for the user event.\n */\nexport type UserEventRequest =\n | {\n /**\n * The context of current CloudEvents request.\n */\n context: ConnectionContext;\n\n /**\n * The content data.\n */\n data: string;\n /**\n * The type of the data.\n */\n dataType: \"text\";\n }\n | {\n /**\n * The context of current CloudEvents request.\n */\n context: ConnectionContext;\n\n /**\n * The content data, when data type is `json`, the data is the result of JSON.parse, so the type of the data depends on user scenarios\n */\n data: unknown;\n\n /**\n * The type of the data.\n */\n dataType: \"json\";\n }\n | {\n /**\n * The context of current CloudEvents request.\n */\n context: ConnectionContext;\n\n /**\n * The content data.\n */\n data: ArrayBuffer;\n /**\n * The type of the data.\n */\n dataType: \"binary\";\n };\n\n/**\n * Request for the disconnected event.\n */\nexport interface DisconnectedRequest {\n /**\n * The context of current CloudEvents request.\n */\n context: ConnectionContext;\n /**\n * The reason that the connection disconnects.\n */\n reason?: string;\n}\n\n/**\n * The handler to set connect event response\n */\nexport interface ConnectResponseHandler {\n /**\n * Set the state of the connection\n * @param name - The name of the state\n * @param value - The value of the state\n */\n setState(name: string, value: unknown): void;\n /**\n * Return success response to the service.\n * @param response - The response for the connect event.\n */\n success(response?: ConnectResponse): void;\n /**\n * Return failed response and the service will reject the client WebSocket connection.\n * @param code - Code can be 400 user error, 401 unauthorized and 500 server error.\n * @param detail - The detail of the error.\n */\n fail(code: 400 | 401 | 500, detail?: string): void;\n}\n\n/**\n * The handler to set user event response\n */\nexport interface UserEventResponseHandler {\n /**\n * Set the state of the connection\n * @param name - The name of the state\n * @param value - The value of the state\n */\n setState(name: string, value: unknown): void;\n /**\n * Return success response with data to be delivered to the client WebSocket connection.\n * @param data - The payload data to be returned to the client. Stringify the message if it is a JSON object.\n * @param dataType - The type of the payload data.\n */\n success(data?: string | ArrayBuffer, dataType?: \"binary\" | \"text\" | \"json\"): void;\n /**\n * Return failed response and the service will close the client WebSocket connection.\n * @param code - Code can be 400 user error, 401 unauthorized and 500 server error.\n * @param detail - The detail of the error.\n */\n fail(code: 400 | 401 | 500, detail?: string): void;\n}\n\n/**\n * The options for the CloudEvents handler.\n */\nexport interface WebPubSubEventHandlerOptions {\n /**\n * Custom serving path for the path of the CloudEvents handler.\n */\n path?: string;\n\n /**\n * Handle 'connect' event, the service waits for the response to proceed.\n */\n handleConnect?: (connectRequest: ConnectRequest, connectResponse: ConnectResponseHandler) => void;\n\n /**\n * Handle user events, the service waits for the response to proceed.\n */\n handleUserEvent?: (\n userEventRequest: UserEventRequest,\n userEventResponse: UserEventResponseHandler\n ) => void;\n\n /**\n * Event trigger for \"connected\" unblocking event. This is an unblocking event and the service does not wait for the response.\n */\n onConnected?: (connectedRequest: ConnectedRequest) => void;\n\n /**\n *\n * Event triggers for \"disconnected\" unblocking event. This is an unblocking event and the service does not wait for the response.\n */\n onDisconnected?: (disconnectedRequest: DisconnectedRequest) => void;\n\n /**\n * If not specified, by default allow all the endpoints, otherwise only allow specified endpoints\n */\n allowedEndpoints?: string[];\n}\n"]}
|
package/dist-esm/src/utils.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
+
import { HTTP } from "cloudevents";
|
|
3
4
|
function isJsonObject(obj) {
|
|
4
5
|
return obj && typeof obj === "object" && !Array.isArray(obj);
|
|
5
6
|
}
|
|
@@ -33,7 +34,7 @@ export function getHttpHeader(req, key) {
|
|
|
33
34
|
export async function convertHttpToEvent(request) {
|
|
34
35
|
const normalized = {
|
|
35
36
|
headers: {},
|
|
36
|
-
body: ""
|
|
37
|
+
body: "",
|
|
37
38
|
};
|
|
38
39
|
if (request.headers) {
|
|
39
40
|
for (const key in request.headers) {
|
|
@@ -45,8 +46,19 @@ export async function convertHttpToEvent(request) {
|
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
|
-
normalized.body = await readRequestBody(request);
|
|
49
|
-
|
|
49
|
+
const body = (normalized.body = await readRequestBody(request));
|
|
50
|
+
const receivedEvent = HTTP.toEvent(normalized);
|
|
51
|
+
if (isJsonData(receivedEvent)) {
|
|
52
|
+
// CloudEvent JSONParser wrap string with quotes however it is not the case for numbers or booleans
|
|
53
|
+
// https://github.com/cloudevents/sdk-javascript/blob/main/src/parsers.ts#L29
|
|
54
|
+
// We workaround it here by rewrite the parsed data property
|
|
55
|
+
receivedEvent.data = JSON.parse(body);
|
|
56
|
+
}
|
|
57
|
+
return receivedEvent;
|
|
58
|
+
}
|
|
59
|
+
export function isJsonData(event) {
|
|
60
|
+
var _a;
|
|
61
|
+
return Boolean((_a = event.datacontenttype) === null || _a === void 0 ? void 0 : _a.startsWith("application/json;"));
|
|
50
62
|
}
|
|
51
63
|
export function readRequestBody(req) {
|
|
52
64
|
return new Promise(function (resolve, reject) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { IncomingMessage } from \"http\";\nimport { CloudEvent, HTTP, Message } from \"cloudevents\";\n\nfunction isJsonObject(obj: any): boolean {\n return obj && typeof obj === \"object\" && !Array.isArray(obj);\n}\n\nexport function toBase64JsonString(obj: Record<string, any>): string {\n return Buffer.from(JSON.stringify(obj)).toString(\"base64\");\n}\n\nexport function fromBase64JsonString(base64String: string): Record<string, any> {\n if (base64String === undefined) {\n return {};\n }\n\n try {\n const buf = Buffer.from(base64String, \"base64\").toString();\n const parsed = JSON.parse(buf);\n return isJsonObject(parsed) ? parsed : {};\n } catch (e) {\n console.warn(\"Unexpected state format:\" + e);\n return {};\n }\n}\n\nexport function getHttpHeader(req: IncomingMessage, key: string): string | undefined {\n const value = req.headers[key];\n if (value === undefined) {\n return undefined;\n }\n\n if (typeof value === \"string\") {\n return value;\n }\n\n return value[0];\n}\n\nexport async function convertHttpToEvent(request: IncomingMessage): Promise<CloudEvent> {\n const normalized: Message = {\n headers: {},\n body: \"\",\n };\n if (request.headers) {\n for (const key in request.headers) {\n if (Object.prototype.hasOwnProperty.call(request.headers, key)) {\n const element = request.headers[key];\n if (element !== undefined) {\n normalized.headers[key.toLowerCase()] = element;\n }\n }\n }\n }\n\n const body = (normalized.body = await readRequestBody(request));\n const receivedEvent = HTTP.toEvent(normalized);\n if (isJsonData(receivedEvent)) {\n // CloudEvent JSONParser wrap string with quotes however it is not the case for numbers or booleans\n // https://github.com/cloudevents/sdk-javascript/blob/main/src/parsers.ts#L29\n // We workaround it here by rewrite the parsed data property\n receivedEvent.data = JSON.parse(body);\n }\n\n return receivedEvent;\n}\n\nexport function isJsonData(event: CloudEvent): boolean {\n return Boolean(event.datacontenttype?.startsWith(\"application/json;\"));\n}\n\nexport function readRequestBody(req: IncomingMessage): Promise<string> {\n return new Promise(function (resolve, reject) {\n const chunks: any = [];\n req.on(\"data\", function (chunk) {\n chunks.push(chunk);\n });\n req.on(\"end\", function () {\n const buffer = Buffer.concat(chunks);\n resolve(buffer.toString());\n });\n // reject on request error\n req.on(\"error\", function (err) {\n // This is not a \"Second reject\", just a different sort of failure\n reject(err);\n });\n });\n}\n"]}
|
|
@@ -74,7 +74,7 @@ describe("Can handle connect event", function () {
|
|
|
74
74
|
const dispatcher = new CloudEventsDispatcher("hub", {
|
|
75
75
|
handleConnect: async (_, response) => {
|
|
76
76
|
response.fail(400);
|
|
77
|
-
}
|
|
77
|
+
},
|
|
78
78
|
});
|
|
79
79
|
const process = dispatcher.handleRequest(req, res);
|
|
80
80
|
mockBody(req, JSON.stringify({}));
|
|
@@ -89,7 +89,7 @@ describe("Can handle connect event", function () {
|
|
|
89
89
|
const dispatcher = new CloudEventsDispatcher("hub", {
|
|
90
90
|
handleConnect: async (_, response) => {
|
|
91
91
|
response.success();
|
|
92
|
-
}
|
|
92
|
+
},
|
|
93
93
|
});
|
|
94
94
|
const process = dispatcher.handleRequest(req, res);
|
|
95
95
|
mockBody(req, JSON.stringify({}));
|
|
@@ -104,7 +104,7 @@ describe("Can handle connect event", function () {
|
|
|
104
104
|
const dispatcher = new CloudEventsDispatcher("hub", {
|
|
105
105
|
handleConnect: async (_, response) => {
|
|
106
106
|
response.success({ userId: "vic" });
|
|
107
|
-
}
|
|
107
|
+
},
|
|
108
108
|
});
|
|
109
109
|
const process = dispatcher.handleRequest(req, res);
|
|
110
110
|
mockBody(req, JSON.stringify({}));
|
|
@@ -123,7 +123,7 @@ describe("Can handle connect event", function () {
|
|
|
123
123
|
response.setState("key1", ["val3"]);
|
|
124
124
|
response.setState("key3", "");
|
|
125
125
|
response.success({ userId: "vic" });
|
|
126
|
-
}
|
|
126
|
+
},
|
|
127
127
|
});
|
|
128
128
|
const process = dispatcher.handleRequest(req, res);
|
|
129
129
|
mockBody(req, JSON.stringify({}));
|
|
@@ -133,7 +133,7 @@ describe("Can handle connect event", function () {
|
|
|
133
133
|
assert.equal(toBase64JsonString({
|
|
134
134
|
key1: ["val3"],
|
|
135
135
|
key2: "val2",
|
|
136
|
-
key3: ""
|
|
136
|
+
key3: "",
|
|
137
137
|
}), res.getHeader("ce-connectionState"), "should contain multiple state headers");
|
|
138
138
|
});
|
|
139
139
|
it("Should be able to get the connection states if it exists in the header", async function () {
|
|
@@ -141,7 +141,7 @@ describe("Can handle connect event", function () {
|
|
|
141
141
|
const states = toBase64JsonString({
|
|
142
142
|
key1: ["val3"],
|
|
143
143
|
key2: "val2",
|
|
144
|
-
key3: ""
|
|
144
|
+
key3: "",
|
|
145
145
|
});
|
|
146
146
|
buildRequest(req, "hub1", "conn1", undefined, states);
|
|
147
147
|
const dispatcher = new CloudEventsDispatcher("hub1", {
|
|
@@ -150,7 +150,7 @@ describe("Can handle connect event", function () {
|
|
|
150
150
|
assert.equal("val2", request.context.states["key2"]);
|
|
151
151
|
assert.equal("", request.context.states["key3"]);
|
|
152
152
|
response.success();
|
|
153
|
-
}
|
|
153
|
+
},
|
|
154
154
|
});
|
|
155
155
|
const process = dispatcher.handleRequest(req, res);
|
|
156
156
|
mockBody(req, JSON.stringify({}));
|
|
@@ -166,7 +166,7 @@ describe("Can handle connect event", function () {
|
|
|
166
166
|
handleConnect: (request, response) => {
|
|
167
167
|
assert.deepEqual({}, request.context.states);
|
|
168
168
|
response.success();
|
|
169
|
-
}
|
|
169
|
+
},
|
|
170
170
|
});
|
|
171
171
|
const process = dispatcher.handleRequest(req, res);
|
|
172
172
|
mockBody(req, JSON.stringify({}));
|