2 /* --------------------------------------------------------------------------------------------
3 * Copyright (c) Microsoft Corporation. All rights reserved.
4 * Licensed under the MIT License. See License.txt in the project root for license information.
5 * ------------------------------------------------------------------------------------------ */
6 Object.defineProperty(exports, "__esModule", { value: true });
7 exports.ReadableStreamMessageReader = exports.AbstractMessageReader = exports.MessageReader = void 0;
8 const ral_1 = require("./ral");
9 const Is = require("./is");
10 const events_1 = require("./events");
12 (function (MessageReader) {
14 let candidate = value;
15 return candidate && Is.func(candidate.listen) && Is.func(candidate.dispose) &&
16 Is.func(candidate.onError) && Is.func(candidate.onClose) && Is.func(candidate.onPartialMessage);
18 MessageReader.is = is;
19 })(MessageReader = exports.MessageReader || (exports.MessageReader = {}));
20 class AbstractMessageReader {
22 this.errorEmitter = new events_1.Emitter();
23 this.closeEmitter = new events_1.Emitter();
24 this.partialMessageEmitter = new events_1.Emitter();
27 this.errorEmitter.dispose();
28 this.closeEmitter.dispose();
31 return this.errorEmitter.event;
34 this.errorEmitter.fire(this.asError(error));
37 return this.closeEmitter.event;
40 this.closeEmitter.fire(undefined);
42 get onPartialMessage() {
43 return this.partialMessageEmitter.event;
45 firePartialMessage(info) {
46 this.partialMessageEmitter.fire(info);
49 if (error instanceof Error) {
53 return new Error(`Reader received error. Reason: ${Is.string(error.message) ? error.message : 'unknown'}`);
57 exports.AbstractMessageReader = AbstractMessageReader;
58 var ResolvedMessageReaderOptions;
59 (function (ResolvedMessageReaderOptions) {
60 function fromOptions(options) {
65 const contentDecoders = new Map();
66 let contentTypeDecoder;
67 const contentTypeDecoders = new Map();
68 if (options === undefined || typeof options === 'string') {
69 charset = options !== null && options !== void 0 ? options : 'utf-8';
72 charset = (_a = options.charset) !== null && _a !== void 0 ? _a : 'utf-8';
73 if (options.contentDecoder !== undefined) {
74 contentDecoder = options.contentDecoder;
75 contentDecoders.set(contentDecoder.name, contentDecoder);
77 if (options.contentDecoders !== undefined) {
78 for (const decoder of options.contentDecoders) {
79 contentDecoders.set(decoder.name, decoder);
82 if (options.contentTypeDecoder !== undefined) {
83 contentTypeDecoder = options.contentTypeDecoder;
84 contentTypeDecoders.set(contentTypeDecoder.name, contentTypeDecoder);
86 if (options.contentTypeDecoders !== undefined) {
87 for (const decoder of options.contentTypeDecoders) {
88 contentTypeDecoders.set(decoder.name, decoder);
92 if (contentTypeDecoder === undefined) {
93 contentTypeDecoder = ral_1.default().applicationJson.decoder;
94 contentTypeDecoders.set(contentTypeDecoder.name, contentTypeDecoder);
96 return { charset, contentDecoder, contentDecoders, contentTypeDecoder, contentTypeDecoders };
98 ResolvedMessageReaderOptions.fromOptions = fromOptions;
99 })(ResolvedMessageReaderOptions || (ResolvedMessageReaderOptions = {}));
100 class ReadableStreamMessageReader extends AbstractMessageReader {
101 constructor(readable, options) {
103 this.readable = readable;
104 this.options = ResolvedMessageReaderOptions.fromOptions(options);
105 this.buffer = ral_1.default().messageBuffer.create(this.options.charset);
106 this._partialMessageTimeout = 10000;
107 this.nextMessageLength = -1;
108 this.messageToken = 0;
110 set partialMessageTimeout(timeout) {
111 this._partialMessageTimeout = timeout;
113 get partialMessageTimeout() {
114 return this._partialMessageTimeout;
117 this.nextMessageLength = -1;
118 this.messageToken = 0;
119 this.partialMessageTimer = undefined;
120 this.callback = callback;
121 const result = this.readable.onData((data) => {
124 this.readable.onError((error) => this.fireError(error));
125 this.readable.onClose(() => this.fireClose());
129 this.buffer.append(data);
131 if (this.nextMessageLength === -1) {
132 const headers = this.buffer.tryReadHeaders();
136 const contentLength = headers.get('Content-Length');
137 if (!contentLength) {
138 throw new Error('Header must provide a Content-Length property.');
140 const length = parseInt(contentLength);
142 throw new Error('Content-Length value must be a number.');
144 this.nextMessageLength = length;
146 const body = this.buffer.tryReadBody(this.nextMessageLength);
147 if (body === undefined) {
148 /** We haven't received the full message yet. */
149 this.setPartialMessageTimer();
152 this.clearPartialMessageTimer();
153 this.nextMessageLength = -1;
155 if (this.options.contentDecoder !== undefined) {
156 p = this.options.contentDecoder.decode(body);
159 p = Promise.resolve(body);
162 this.options.contentTypeDecoder.decode(value, this.options).then((msg) => {
165 this.fireError(error);
168 this.fireError(error);
172 clearPartialMessageTimer() {
173 if (this.partialMessageTimer) {
174 ral_1.default().timer.clearTimeout(this.partialMessageTimer);
175 this.partialMessageTimer = undefined;
178 setPartialMessageTimer() {
179 this.clearPartialMessageTimer();
180 if (this._partialMessageTimeout <= 0) {
183 this.partialMessageTimer = ral_1.default().timer.setTimeout((token, timeout) => {
184 this.partialMessageTimer = undefined;
185 if (token === this.messageToken) {
186 this.firePartialMessage({ messageToken: token, waitingTime: timeout });
187 this.setPartialMessageTimer();
189 }, this._partialMessageTimeout, this.messageToken, this._partialMessageTimeout);
192 exports.ReadableStreamMessageReader = ReadableStreamMessageReader;
193 //# sourceMappingURL=messageReader.js.map