UNPKG

@zowe/imperative

Version:
125 lines 5.11 kB
"use strict"; /* * This program and the accompanying materials are made available under the terms of the * Eclipse Public License v2.0 which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-v20.html * * SPDX-License-Identifier: EPL-2.0 * * Copyright Contributors to the Zowe Project. * */ Object.defineProperty(exports, "__esModule", { value: true }); exports.CompressionUtils = void 0; const stream_1 = require("stream"); const zlib = require("zlib"); const error_1 = require("../../../error"); const io_1 = require("../../../io"); const Headers_1 = require("./Headers"); class CompressionUtils { /** * Decompress a buffer using the specified algorithm. * @param data Compressed buffer * @param encoding Value of Content-Encoding header * @throws {ImperativeError} */ static decompressBuffer(data, encoding) { if (!Headers_1.Headers.CONTENT_ENCODING_TYPES.includes(encoding)) { throw new error_1.ImperativeError({ msg: `Unsupported content encoding type ${encoding}` }); } try { switch (encoding) { case "br": return zlib.brotliDecompressSync(data); case "deflate": return zlib.inflateSync(data); case "gzip": return zlib.gunzipSync(data); } } catch (err) { throw this.decompressError(err, "buffer", encoding); } } /** * Add zlib decompression transform to a Writable stream. Any compressed * data written to the returned stream will be decompressed using the * specified algorithm. * * The returned stream should only be used internally by a REST client to * write to. Use the original stream to read back the decompressed output * and handle decompression errors. * @param responseStream Writable stream that will receive compressed data * @param encoding Value of Content-Encoding header * @param normalizeNewLines Specifies if line endings should be converted * @throws {ImperativeError} */ static decompressStream(responseStream, encoding, normalizeNewLines) { if (!Headers_1.Headers.CONTENT_ENCODING_TYPES.includes(encoding)) { throw new error_1.ImperativeError({ msg: `Unsupported content encoding type ${encoding}` }); } try { // First transform handles decompression const transforms = [this.zlibTransform(encoding, !normalizeNewLines)]; // Second transform is optional and processes line endings if (normalizeNewLines) { transforms.push(this.newLinesTransform()); } // Chain transforms and response stream together for (const [i, stream] of transforms.entries()) { const next = transforms[i + 1] || responseStream; stream.pipe(next); stream.on("error", (err) => { responseStream.emit("error", this.decompressError(err, "stream", encoding)); }); } // Return first stream in chain return transforms[0]; } catch (err) { throw this.decompressError(err, "stream", encoding); } } /** * Return ImperativeError populated with details of decompression error * @param err Thrown error object * @param source Type of object being decompressed * @param encoding Value of Content-Encoding header */ static decompressError(err, source, encoding) { return new error_1.ImperativeError({ msg: `Failed to decompress response ${source} with content encoding type ${encoding}`, additionalDetails: err.message, causeErrors: err }); } /** * Return a transform to normalize line endings in response text. */ static newLinesTransform() { let lastByteReceived = 0; return new stream_1.Transform({ transform(chunk, _, callback) { this.push(io_1.IO.processNewlines(chunk, lastByteReceived)); lastByteReceived = chunk[chunk.byteLength - 1]; callback(); } }); } /** * Return zlib transform for the specified decompression algorithm. * @param encoding Value of Content-Encoding header */ static zlibTransform(encoding, binary) { const opts = {}; if (binary) { // Handle binary data that may be truncated or missing the GZIP end of file sequence. // See https://nodejs.org/api/zlib.html#compressing-http-requests-and-responses opts.finishFlush = encoding === "br" ? zlib.constants.BROTLI_OPERATION_FLUSH : zlib.constants.Z_SYNC_FLUSH; } switch (encoding) { case "br": return zlib.createBrotliDecompress(opts); case "deflate": return zlib.createInflate(opts); case "gzip": return zlib.createGunzip(opts); } } } exports.CompressionUtils = CompressionUtils; //# sourceMappingURL=CompressionUtils.js.map