Skip to content

Commit f92d579

Browse files
Copiloticlanton
andauthored
Handle Content-Encoding decompression in streaming WebClient path
Agent-Logs-Url: https://github.com/microsoft/rushstack/sessions/13978d72-ea9a-4463-a6a2-51ecfc72f3ff Co-authored-by: iclanton <5010588+iclanton@users.noreply.github.com>
1 parent a130c6d commit f92d579

1 file changed

Lines changed: 49 additions & 2 deletions

File tree

libraries/rush-lib/src/utilities/WebClient.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ const makeStreamRequestAsync: StreamFetchFn = async (
274274
options: IRequestOptions,
275275
redirected: boolean = false
276276
) => {
277+
const { noDecode } = options;
278+
277279
return _makeRawRequestAsync(
278280
url,
279281
options,
@@ -284,14 +286,59 @@ const makeStreamRequestAsync: StreamFetchFn = async (
284286
resolve: (result: IWebClientStreamResponse | PromiseLike<IWebClientStreamResponse>) => void
285287
): void => {
286288
const { statusCode: status = 0, statusMessage: statusText, headers } = response;
287-
resolve({
289+
290+
const buildResult = (stream: Readable): IWebClientStreamResponse => ({
288291
ok: status >= 200 && status < 300,
289292
status,
290293
statusText,
291294
redirected: wasRedirected,
292295
headers,
293-
stream: response
296+
stream
294297
});
298+
299+
// Handle Content-Encoding decompression for streaming responses,
300+
// matching the buffer-based path's behavior in getBufferAsync()
301+
let encodings: string | string[] | undefined;
302+
if (!noDecode) {
303+
encodings = headers[CONTENT_ENCODING_HEADER_NAME];
304+
}
305+
306+
if (encodings !== undefined) {
307+
// Resolve with a promise so we can lazily import zlib (same pattern as buffer path)
308+
resolve(
309+
(async () => {
310+
const zlib: typeof import('zlib') = await import('node:zlib');
311+
if (!Array.isArray(encodings)) {
312+
encodings = encodings!.split(',');
313+
}
314+
315+
let resultStream: Readable = response;
316+
for (const encoding of encodings) {
317+
switch (encoding.trim()) {
318+
case DEFLATE_ENCODING: {
319+
resultStream = resultStream.pipe(zlib.createInflate());
320+
break;
321+
}
322+
case GZIP_ENCODING: {
323+
resultStream = resultStream.pipe(zlib.createGunzip());
324+
break;
325+
}
326+
case BROTLI_ENCODING: {
327+
resultStream = resultStream.pipe(zlib.createBrotliDecompress());
328+
break;
329+
}
330+
default: {
331+
throw new Error(`Unsupported content-encoding: ${encodings}`);
332+
}
333+
}
334+
}
335+
336+
return buildResult(resultStream);
337+
})()
338+
);
339+
} else {
340+
resolve(buildResult(response));
341+
}
295342
},
296343
makeStreamRequestAsync
297344
);

0 commit comments

Comments
 (0)