From cf64ee2e01e689ba2657acce914ba9c3febd9a2d Mon Sep 17 00:00:00 2001 From: Flummi Date: Tue, 18 Mar 2025 12:55:28 +0100 Subject: [PATCH] feat: add gzip and deflate decompression support and request timeout option --- dist/index.js | 15 ++++++++++++++- src/index.ts | 18 +++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 1229f14..4027acd 100644 --- a/dist/index.js +++ b/dist/index.js @@ -2,13 +2,21 @@ import http from "http"; import https from "https"; import { URL } from "url"; import querystring from "querystring"; +import zlib from "zlib"; +const decompress = (data, header) => { + if (header === "gzip") + return zlib.gunzipSync(data); + if (header === "deflate") + return zlib.inflateSync(data); + return data; +}; const readData = (res, mode) => new Promise((resolve, reject) => { const chunks = []; res .on("data", chunk => chunks.push(chunk)) .on("end", () => { - const data = Buffer.concat(chunks); try { + const data = decompress(Buffer.concat(chunks), res.headers["content-encoding"]); if (mode === "json") resolve(JSON.parse(data.toString("utf8"))); else if (mode === "buffer") @@ -39,6 +47,7 @@ export default async (urlString, options = {}) => { headers: { ...options.headers, ...(body ? { "Content-Length": Buffer.byteLength(body) } : {}), + "Accept-Encoding": "gzip, deflate" } }; return new Promise((resolve, reject) => { @@ -55,6 +64,10 @@ export default async (urlString, options = {}) => { arrayBuffer: () => readData(res, "arraybuffer") }); }); + req.setTimeout(options.timeout || 5e3, () => { + req.destroy(); + reject(new Error("Request timed out")); + }); req.on("error", reject); if (body) req.write(body); diff --git a/src/index.ts b/src/index.ts index 9a76b2a..16a0e45 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ import http from "http"; import https from "https"; import { URL } from "url"; import querystring from "querystring"; +import zlib from "zlib"; type ResponseData = { body: http.IncomingMessage; @@ -14,8 +15,17 @@ type ResponseData = { interface ExtendedRequestOptions extends http.RequestOptions { body?: any; + timeout?: number; } +const decompress = (data: Buffer, header: string | undefined): Buffer => { + if(header === "gzip") + return zlib.gunzipSync(data); + if(header === "deflate") + return zlib.inflateSync(data); + return data; +}; + const readData = ( res: http.IncomingMessage, mode: "text" | "json" | "buffer" | "arraybuffer" @@ -25,8 +35,8 @@ const readData = ( res .on("data", chunk => chunks.push(chunk)) .on("end", () => { - const data = Buffer.concat(chunks); try { + const data = decompress(Buffer.concat(chunks), res.headers["content-encoding"]); if(mode === "json") resolve(JSON.parse(data.toString("utf8"))); else if(mode === "buffer") @@ -64,6 +74,7 @@ export default async ( headers: { ...options.headers, ...(body ? { "Content-Length": Buffer.byteLength(body) } : {}), + "Accept-Encoding": "gzip, deflate" } }; @@ -82,6 +93,11 @@ export default async ( }); }); + req.setTimeout(options.timeout || 5e3, () => { + req.destroy(); + reject(new Error("Request timed out")); + }); + req.on("error", reject); if(body) req.write(body);