151 lines
No EOL
6.4 KiB
JavaScript
151 lines
No EOL
6.4 KiB
JavaScript
"use strict";
|
|
/**
|
|
* @module botframework-streaming
|
|
*/
|
|
/**
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License.
|
|
*/
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.PayloadAssembler = void 0;
|
|
const subscribableStream_1 = require("../subscribableStream");
|
|
const payloads_1 = require("../payloads");
|
|
const contentStream_1 = require("../contentStream");
|
|
/**
|
|
* Assembles payloads for streaming library.
|
|
*
|
|
* @internal
|
|
*/
|
|
class PayloadAssembler {
|
|
/**
|
|
* Initializes a new instance of the [PayloadAssembler](xref:botframework-streaming.PayloadAssembler) class.
|
|
*
|
|
* @param streamManager The [StreamManager](xref:botframework-streaming.StreamManager) managing the stream being assembled.
|
|
* @param params Parameters for a streaming assembler.
|
|
*/
|
|
constructor(streamManager, params) {
|
|
this.streamManager = streamManager;
|
|
this._byteOrderMark = 0xfeff;
|
|
this._utf = 'utf8';
|
|
if (params.header) {
|
|
this.id = params.header.id;
|
|
this.payloadType = params.header.payloadType;
|
|
this.contentLength = params.header.payloadLength;
|
|
this.end = params.header.end;
|
|
}
|
|
else {
|
|
this.id = params.id;
|
|
}
|
|
if (!this.id) {
|
|
throw Error('An ID must be supplied when creating an assembler.');
|
|
}
|
|
this._onCompleted = params.onCompleted;
|
|
}
|
|
/**
|
|
* Retrieves the assembler's payload as a stream.
|
|
*
|
|
* @returns A [SubscribableStream](xref:botframework-streaming.SubscribableStream) of the assembler's payload.
|
|
*/
|
|
getPayloadStream() {
|
|
if (!this.stream) {
|
|
this.stream = this.createPayloadStream();
|
|
}
|
|
return this.stream;
|
|
}
|
|
/**
|
|
* The action the assembler executes when new bytes are received on the incoming stream.
|
|
*
|
|
* @param header The stream's Header.
|
|
* @param stream The incoming stream being assembled.
|
|
* @param _contentLength The length of the stream, if finite.
|
|
*/
|
|
onReceive(header, stream, _contentLength) {
|
|
this.end = header.end;
|
|
if (header.payloadType === payloads_1.PayloadTypes.response || header.payloadType === payloads_1.PayloadTypes.request) {
|
|
this.process(stream).then().catch();
|
|
}
|
|
else if (header.end) {
|
|
stream.end();
|
|
}
|
|
}
|
|
/**
|
|
* Closes the assembler.
|
|
*/
|
|
close() {
|
|
this.streamManager.closeStream(this.id);
|
|
}
|
|
/**
|
|
* Creates a new [SubscribableStream](xref:botframework-streaming.SubscribableStream) instance.
|
|
*
|
|
* @returns The new stream ready for consumption.
|
|
*/
|
|
createPayloadStream() {
|
|
return new subscribableStream_1.SubscribableStream();
|
|
}
|
|
payloadFromJson(json) {
|
|
return JSON.parse(json.charCodeAt(0) === this._byteOrderMark ? json.slice(1) : json);
|
|
}
|
|
stripBOM(input) {
|
|
return input.charCodeAt(0) === this._byteOrderMark ? input.slice(1) : input;
|
|
}
|
|
process(stream) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const streamData = stream.read(stream.length);
|
|
if (!streamData) {
|
|
return;
|
|
}
|
|
const streamDataAsString = streamData.toString(this._utf);
|
|
if (this.payloadType === payloads_1.PayloadTypes.request) {
|
|
yield this.processRequest(streamDataAsString);
|
|
}
|
|
else if (this.payloadType === payloads_1.PayloadTypes.response) {
|
|
yield this.processResponse(streamDataAsString);
|
|
}
|
|
});
|
|
}
|
|
processResponse(streamDataAsString) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const responsePayload = this.payloadFromJson(this.stripBOM(streamDataAsString));
|
|
const receiveResponse = { streams: [], statusCode: responsePayload.statusCode };
|
|
yield this.processStreams(responsePayload, receiveResponse);
|
|
});
|
|
}
|
|
processRequest(streamDataAsString) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const requestPayload = this.payloadFromJson(streamDataAsString);
|
|
const receiveRequest = { streams: [], path: requestPayload.path, verb: requestPayload.verb };
|
|
yield this.processStreams(requestPayload, receiveRequest);
|
|
});
|
|
}
|
|
processStreams(responsePayload, receiveResponse) {
|
|
var _a;
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
(_a = responsePayload.streams) === null || _a === void 0 ? void 0 : _a.forEach((responseStream) => {
|
|
var _a;
|
|
// There was a bug in how streams were handled. In .NET, the StreamDescription definiton mapped the
|
|
// "type" JSON property to `contentType`, but in Typescript there was no mapping. This is a workaround
|
|
// to resolve this inconsistency.
|
|
//
|
|
// .NET code:
|
|
// https://github.com/microsoft/botbuilder-dotnet/blob/a79036ddf6625ec3fd68a6f7295886eb7831bc1c/libraries/Microsoft.Bot.Streaming/Payloads/Models/StreamDescription.cs#L28-L29
|
|
const contentType = (_a = responseStream.type) !== null && _a !== void 0 ? _a : responseStream.contentType;
|
|
const contentAssembler = this.streamManager.getPayloadAssembler(responseStream.id);
|
|
contentAssembler.payloadType = contentType;
|
|
contentAssembler.contentLength = responseStream.length;
|
|
receiveResponse.streams.push(new contentStream_1.ContentStream(responseStream.id, contentAssembler));
|
|
});
|
|
yield this._onCompleted(this.id, receiveResponse);
|
|
});
|
|
}
|
|
}
|
|
exports.PayloadAssembler = PayloadAssembler;
|
|
//# sourceMappingURL=payloadAssembler.js.map
|