Skip to content

Commit

Permalink
fix(utils): now parseUndiciResponse handles compressed data before to…
Browse files Browse the repository at this point in the history
… converting it (#223)
  • Loading branch information
SofianD committed Jan 25, 2024
1 parent 56ac50c commit a266377
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 3 deletions.
17 changes: 14 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/* eslint-disable no-redeclare */

// Import Node.js Dependencies
import { IncomingHttpHeaders } from "http";
import { gunzip } from "node:zlib";
import { promisify } from "node:util";
import { IncomingHttpHeaders } from "node:http";

// Import Third-party Dependencies
import * as contentType from "content-type";
Expand All @@ -17,6 +19,7 @@ const kDefaultEncodingCharset = "utf-8";
const kCharsetConversionTable = {
"ISO-8859-1": "latin1"
};
const kAsyncGunzip = promisify(gunzip);

export const DEFAULT_HEADER = { "user-agent": kDefaultUserAgent };

Expand All @@ -41,13 +44,21 @@ export function getEncodingCharset(charset = kDefaultEncodingCharset): BufferEnc
* If the response as a content type equal to 'application/json' we automatically parse it with JSON.parse().
*/
export async function parseUndiciResponse<T>(response: Dispatcher.ResponseData): Promise<T | string> {
const body = await response.body.text();
const contentTypeHeader = response.headers["content-type"] as string | undefined;
const { type } = contentType.parse(
const { type, parameters } = contentType.parse(
contentTypeHeader ?? kDefaultMimeType
);

let body;
try {
if (response.headers["content-encoding"] === "gzip") {
const buf = await response.body.arrayBuffer();
body = (await kAsyncGunzip(buf)).toString(getEncodingCharset(parameters.charset));
}
else {
body = await response.body.text();
}

return type === "application/json" && body ? JSON.parse(body) : body;
}
catch (error) {
Expand Down
49 changes: 49 additions & 0 deletions test/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Import Node.js Dependencies
import { IncomingHttpHeaders } from "http2";
import { gzipSync } from "zlib";
import stream from "stream";

// Import Internal Dependencies
Expand Down Expand Up @@ -217,6 +218,54 @@ describe("parseUndiciResponse", () => {

expect(data).toStrictEqual(payload);
});

it("must unzip data when there is a 'content-encoding' header set with 'gzip' before to converting it to a string", async() => {
const payload = "hello world!";
const body: any = {
async arrayBuffer() {
return gzipSync(payload);
}
};
const data = await Utils.parseUndiciResponse<string>({
...defaultUndiciResponseMeta, body, headers: {
"content-encoding": "gzip"
}
});

expect(data).toStrictEqual(payload);
});

it("must unzip data when there is a 'content-encoding' header set with 'gzip' before to converting it to JSON", async() => {
const payload = { foo: "hello world!" };
const body: any = {
async arrayBuffer() {
return gzipSync(JSON.stringify(payload));
}
};

const data = await Utils.parseUndiciResponse<string>({
...defaultUndiciResponseMeta, body, headers: {
"content-encoding": "gzip",
"content-type": "application/json; charset=utf-8"
}
});

expect(data).toStrictEqual(payload);
});

it("should not unzip data when 'content-encoding' header is not set", async() => {
const payload = "hello world!";
const buf = gzipSync(payload);
const body: any = {
text: () => buf.toString()
};

const data = await Utils.parseUndiciResponse<string>({
...defaultUndiciResponseMeta, body, headers: {}
});

expect(data).toStrictEqual(buf.toString());
});
});

describe("getCurrentEnv", () => {
Expand Down

0 comments on commit a266377

Please sign in to comment.