From 25679f34c3b748e15d577924e2b6b4a9f54af649 Mon Sep 17 00:00:00 2001 From: Sahil1337 Date: Tue, 7 Jul 2026 12:17:57 +0530 Subject: [PATCH 1/2] refactor: remove unused utility files and typings - Deleted utility files: index.js, logger.js, native.js, request.js, tlsError.js from dist/utils. - Removed corresponding typings from typings/utils and typings/interface. - Cleaned up workers/index.js and typings/workers/index.d.ts by removing unused exports. - Eliminated unnecessary Client, Cookie, Response, Session, and requests typings from typings/lib. - Streamlined the overall codebase by removing redundant interfaces and types. --- dist/index.js | 18 -- dist/interface/client.js | 2 - dist/interface/index.js | 18 -- dist/interface/native.js | 2 - dist/interface/payload.js | 2 - dist/interface/session.js | 85 ------ dist/lib/Client.js | 65 ----- dist/lib/Cookie.js | 57 ---- dist/lib/Response.js | 43 --- dist/lib/Session.js | 196 ------------- dist/lib/index.js | 20 -- dist/lib/requests.js | 52 ---- dist/lib/tlsClient.js | 11 - dist/utils/download.js | 188 ------------- dist/utils/index.js | 20 -- dist/utils/logger.js | 33 --- dist/utils/native.js | 79 ------ dist/utils/request.js | 55 ---- dist/utils/tlsError.js | 14 - dist/workers/index.js | 27 -- typings/index.d.ts | 2 - typings/interface/client.d.ts | 7 - typings/interface/index.d.ts | 2 - typings/interface/native.d.ts | 18 -- typings/interface/payload.d.ts | 55 ---- typings/interface/session.d.ts | 493 --------------------------------- typings/lib/Client.d.ts | 13 - typings/lib/Cookie.d.ts | 35 --- typings/lib/Response.d.ts | 24 -- typings/lib/Session.d.ts | 82 ------ typings/lib/index.d.ts | 4 - typings/lib/requests.d.ts | 11 - typings/lib/tlsClient.d.ts | 2 - typings/utils/download.d.ts | 12 - typings/utils/index.d.ts | 4 - typings/utils/logger.d.ts | 15 - typings/utils/native.d.ts | 10 - typings/utils/request.d.ts | 12 - typings/utils/tlsError.d.ts | 3 - typings/workers/index.d.ts | 5 - 40 files changed, 1796 deletions(-) delete mode 100644 dist/index.js delete mode 100644 dist/interface/client.js delete mode 100644 dist/interface/index.js delete mode 100644 dist/interface/native.js delete mode 100644 dist/interface/payload.js delete mode 100644 dist/interface/session.js delete mode 100644 dist/lib/Client.js delete mode 100644 dist/lib/Cookie.js delete mode 100644 dist/lib/Response.js delete mode 100644 dist/lib/Session.js delete mode 100644 dist/lib/index.js delete mode 100644 dist/lib/requests.js delete mode 100644 dist/lib/tlsClient.js delete mode 100644 dist/utils/download.js delete mode 100644 dist/utils/index.js delete mode 100644 dist/utils/logger.js delete mode 100644 dist/utils/native.js delete mode 100644 dist/utils/request.js delete mode 100644 dist/utils/tlsError.js delete mode 100644 dist/workers/index.js delete mode 100644 typings/index.d.ts delete mode 100644 typings/interface/client.d.ts delete mode 100644 typings/interface/index.d.ts delete mode 100644 typings/interface/native.d.ts delete mode 100644 typings/interface/payload.d.ts delete mode 100644 typings/interface/session.d.ts delete mode 100644 typings/lib/Client.d.ts delete mode 100644 typings/lib/Cookie.d.ts delete mode 100644 typings/lib/Response.d.ts delete mode 100644 typings/lib/Session.d.ts delete mode 100644 typings/lib/index.d.ts delete mode 100644 typings/lib/requests.d.ts delete mode 100644 typings/lib/tlsClient.d.ts delete mode 100644 typings/utils/download.d.ts delete mode 100644 typings/utils/index.d.ts delete mode 100644 typings/utils/logger.d.ts delete mode 100644 typings/utils/native.d.ts delete mode 100644 typings/utils/request.d.ts delete mode 100644 typings/utils/tlsError.d.ts delete mode 100644 typings/workers/index.d.ts diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index ea570db..0000000 --- a/dist/index.js +++ /dev/null @@ -1,18 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -__exportStar(require("./interface"), exports); -__exportStar(require("./lib"), exports); diff --git a/dist/interface/client.js b/dist/interface/client.js deleted file mode 100644 index c8ad2e5..0000000 --- a/dist/interface/client.js +++ /dev/null @@ -1,2 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/interface/index.js b/dist/interface/index.js deleted file mode 100644 index fc6eb9d..0000000 --- a/dist/interface/index.js +++ /dev/null @@ -1,18 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -__exportStar(require("./session"), exports); -__exportStar(require("./client"), exports); diff --git a/dist/interface/native.js b/dist/interface/native.js deleted file mode 100644 index c8ad2e5..0000000 --- a/dist/interface/native.js +++ /dev/null @@ -1,2 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/interface/payload.js b/dist/interface/payload.js deleted file mode 100644 index c8ad2e5..0000000 --- a/dist/interface/payload.js +++ /dev/null @@ -1,2 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/interface/session.js b/dist/interface/session.js deleted file mode 100644 index f3ec85f..0000000 --- a/dist/interface/session.js +++ /dev/null @@ -1,85 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClientIdentifier = void 0; -/** - * Represents various client identifiers. - * - * The client identifiers are grouped by browser, mobile clients, and other clients. - */ -var ClientIdentifier; -(function (ClientIdentifier) { - // Chrome versions - ClientIdentifier["chrome_103"] = "chrome_103"; - ClientIdentifier["chrome_104"] = "chrome_104"; - ClientIdentifier["chrome_105"] = "chrome_105"; - ClientIdentifier["chrome_106"] = "chrome_106"; - ClientIdentifier["chrome_107"] = "chrome_107"; - ClientIdentifier["chrome_108"] = "chrome_108"; - ClientIdentifier["chrome_109"] = "chrome_109"; - ClientIdentifier["chrome_110"] = "chrome_110"; - ClientIdentifier["chrome_111"] = "chrome_111"; - ClientIdentifier["chrome_112"] = "chrome_112"; - ClientIdentifier["chrome_116_PSK"] = "chrome_116_PSK"; - ClientIdentifier["chrome_116_PSK_PQ"] = "chrome_116_PSK_PQ"; - ClientIdentifier["chrome_117"] = "chrome_117"; - ClientIdentifier["chrome_120"] = "chrome_120"; - ClientIdentifier["chrome_124"] = "chrome_124"; - ClientIdentifier["chrome_131"] = "chrome_131"; - ClientIdentifier["chrome_131_psk"] = "chrome_131_PSK"; - // Safari versions - ClientIdentifier["safari_15_6_1"] = "safari_15_6_1"; - ClientIdentifier["safari_16_0"] = "safari_16_0"; - ClientIdentifier["safari_ipad_15_6"] = "safari_ipad_15_6"; - ClientIdentifier["safari_ios_15_5"] = "safari_ios_15_5"; - ClientIdentifier["safari_ios_15_6"] = "safari_ios_15_6"; - ClientIdentifier["safari_ios_16_0"] = "safari_ios_16_0"; - ClientIdentifier["safari_ios_17_0"] = "safari_ios_17_0"; - ClientIdentifier["safari_ios_18_0"] = "safari_ios_18_0"; - // Firefox versions - ClientIdentifier["firefox_102"] = "firefox_102"; - ClientIdentifier["firefox_104"] = "firefox_104"; - ClientIdentifier["firefox_105"] = "firefox_105"; - ClientIdentifier["firefox_106"] = "firefox_106"; - ClientIdentifier["firefox_108"] = "firefox_108"; - ClientIdentifier["firefox_110"] = "firefox_110"; - ClientIdentifier["firefox_117"] = "firefox_117"; - ClientIdentifier["firefox_120"] = "firefox_120"; - ClientIdentifier["firefox_123"] = "firefox_123"; - ClientIdentifier["firefox_132"] = "firefox_132"; - ClientIdentifier["firefox_133"] = "firefox_133"; - // Opera versions - ClientIdentifier["opera_89"] = "opera_89"; - ClientIdentifier["opera_90"] = "opera_90"; - ClientIdentifier["opera_91"] = "opera_91"; - // Zalando mobile clients - ClientIdentifier["zalando_android_mobile"] = "zalando_android_mobile"; - ClientIdentifier["zalando_ios_mobile"] = "zalando_ios_mobile"; - // Nike mobile clients - ClientIdentifier["nike_ios_mobile"] = "nike_ios_mobile"; - ClientIdentifier["nike_android_mobile"] = "nike_android_mobile"; - // Other clients - ClientIdentifier["cloudscraper"] = "cloudscraper"; - // MMS iOS versions - ClientIdentifier["mms_ios"] = "mms_ios"; - ClientIdentifier["mms_ios_1"] = "mms_ios_1"; - ClientIdentifier["mms_ios_2"] = "mms_ios_2"; - ClientIdentifier["mms_ios_3"] = "mms_ios_3"; - // Mesh clients - ClientIdentifier["mesh_ios"] = "mesh_ios"; - ClientIdentifier["mesh_ios_1"] = "mesh_ios_1"; - ClientIdentifier["mesh_ios_2"] = "mesh_ios_2"; - ClientIdentifier["mesh_android"] = "mesh_android"; - ClientIdentifier["mesh_android_1"] = "mesh_android_1"; - ClientIdentifier["mesh_android_2"] = "mesh_android_2"; - // Confirmed clients - ClientIdentifier["confirmed_ios"] = "confirmed_ios"; - ClientIdentifier["confirmed_android"] = "confirmed_android"; - // OkHttp Android versions - ClientIdentifier["okhttp4_android_7"] = "okhttp4_android_7"; - ClientIdentifier["okhttp4_android_8"] = "okhttp4_android_8"; - ClientIdentifier["okhttp4_android_9"] = "okhttp4_android_9"; - ClientIdentifier["okhttp4_android_10"] = "okhttp4_android_10"; - ClientIdentifier["okhttp4_android_11"] = "okhttp4_android_11"; - ClientIdentifier["okhttp4_android_12"] = "okhttp4_android_12"; - ClientIdentifier["okhttp4_android_13"] = "okhttp4_android_13"; -})(ClientIdentifier || (exports.ClientIdentifier = ClientIdentifier = {})); diff --git a/dist/lib/Client.js b/dist/lib/Client.js deleted file mode 100644 index b01f1dc..0000000 --- a/dist/lib/Client.js +++ /dev/null @@ -1,65 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Client = void 0; -const piscina_1 = require("piscina"); -const native_1 = require("../utils/native"); -const utils_1 = require("../utils"); -const os_1 = __importDefault(require("os")); -class Client { - static instance = null; - static ready = false; - static readyPromise = null; - _pool; - constructor() { - this._pool = new piscina_1.Piscina({ - filename: require.resolve("../workers/index.js"), - maxQueue: Infinity, - maxThreads: (typeof os_1.default.availableParallelism === "function" - ? os_1.default.availableParallelism() - : os_1.default.cpus().length) * 2, - atomics: "disabled", - }); - } - static async init() { - if (Client.ready) - return; - if (!Client.readyPromise) { - // Initialize ready promise - Client.readyPromise = (async () => { - await native_1.LibraryHandler.validateFile(); - Client.instance = new Client(); - Client.ready = true; - Client.readyPromise = null; - })(); - } - return Client.readyPromise; - } - static async destroy() { - if (!Client.instance) { - throw new utils_1.TlsClientError("Client not initialized. Call initTLS() first."); - } - // Clear sessions cache - await Client.instance.pool.run({}, { name: "destroyAll" }); - // Destroy worker pool - await Client.instance.pool.close(); - // Reset instance - Client.instance = null; - Client.ready = false; - } - static getInstance() { - if (!Client.instance) { - throw new utils_1.TlsClientError("Client not initialized. Call initTLS() first."); - } - return Client.instance; - } - get pool() { - return this._pool; - } - static isReady() { - return Client.ready; - } -} -exports.Client = Client; diff --git a/dist/lib/Cookie.js b/dist/lib/Cookie.js deleted file mode 100644 index a00ab45..0000000 --- a/dist/lib/Cookie.js +++ /dev/null @@ -1,57 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Cookies = void 0; -const tough_cookie_1 = require("tough-cookie"); -class Cookies extends tough_cookie_1.CookieJar { - constructor() { - super(); - } - /** - * Fetches all cookies and organizes them by URL. - * - * This method serializes cookies and groups them by their domain and path, - * constructing a URL as the key and an object of cookies as key-value pairs. - * - * @returns A promise that resolves to an object where keys are URLs and values are objects containing cookies as key-value pairs. - */ - async fetchAllCookies() { - return (await this.serialize()).cookies; - } - /** - * Syncs cookies with the provided URL. - * - * @param cookies - An object containing cookies as key-value pairs. - * @param url - The URL for which cookies are to be set. - * @returns A promise that resolves to an object containing the synced cookies. - */ - async syncCookies(cookies, url) { - if (!cookies) - return {}; - const result = {}; - await Promise.all(Object.entries(cookies).map(async ([key, value]) => { - const cookie = await this.setCookie(`${key}=${value}`, url); - result[cookie.key] = cookie.value; - })); - return result; - } - /** - * Merges the provided cookies with the existing cookies for a given URL according to request payload. - * - * @param cookies - An object containing cookies as key-value pairs. - * @param url - The URL for which cookies are to be set. - * @returns A promise that resolves to an array of objects, each containing the name and value of a cookie. - * - * @example - * mergeCookies({ 'cookie1': 'value1', 'cookie2': 'value2' }, 'http://example.com') - */ - async mergeCookies(cookies, url) { - return Promise.all(Object.entries(cookies).map(async ([key, value]) => { - const cookie = await this.setCookie(`${key}=${value}`, url); - return { - name: cookie.key, - value: cookie.value, - }; - })); - } -} -exports.Cookies = Cookies; diff --git a/dist/lib/Response.js b/dist/lib/Response.js deleted file mode 100644 index d157ecd..0000000 --- a/dist/lib/Response.js +++ /dev/null @@ -1,43 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Response = void 0; -class Response { - // Indicates whether the response was successful (status in the range 200-299) or not. - ok; - // Represents the response headers. - headers; - // Represents the HTTP status code of the response. - status; - // Represents the URL of the response. - url; - // The response body - body; - // The cookies from the response - cookies; - constructor(response) { - this.ok = response.status >= 200 && response.status < 300; - this.headers = response.headers; - this.status = response.status; - this.url = response.target; - this.body = response.body; - this.cookies = response.cookies; - } - /** - * Returns the body of the response as a string. - * - * @returns A promise that resolves with the body of the response as a string. - */ - async text() { - return this.body; - } - /** - * Returns the body of the response as a JSON object. - * - * @typeparam T - The type of the JSON object. - * @returns A promise that resolves with the body of the response as a JSON object. - */ - async json() { - return JSON.parse(this.body); - } -} -exports.Response = Response; diff --git a/dist/lib/Session.js b/dist/lib/Session.js deleted file mode 100644 index f79e7d8..0000000 --- a/dist/lib/Session.js +++ /dev/null @@ -1,196 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Session = void 0; -const crypto_1 = require("crypto"); -const Cookie_1 = require("./Cookie"); -const interface_1 = require("../interface"); -const utils_1 = require("../utils"); -const Client_1 = require("./Client"); -const Response_1 = require("./Response"); -const __version__ = "2.1.0"; -class Session { - config; - jar = new Cookie_1.Cookies(); - sessionId = (0, crypto_1.randomUUID)(); - constructor(config = {}) { - this.config = config; - } - async cookies() { - return this.jar.fetchAllCookies(); - } - /** - * The 'GET' method performs a GET request to the provided URL with the provided options. - * - * @param url - The URL to perform the GET request to. - * @param options - The options for the GET request. - * - * @returns The response from the 'execute' method. - */ - get(url, options = {}) { - return this.execute("GET", url, options); - } - /** - * The 'DELETE' method performs a DELETE request to the provided URL with the provided options. - * - * @param url - The URL to perform the DELETE request to. - * @param options - The options for the DELETE request. - * - * @returns The response from the 'execute' method. - */ - delete(url, options = {}) { - return this.execute("DELETE", url, options); - } - /** - * The 'OPTIONS' method performs an OPTIONS request to the provided URL with the provided options. - * - * @param url - The URL to perform the OPTIONS request to. - * @param options - The options for the OPTIONS request. - * - * @returns The response from the 'execute' method. - */ - options(url, options = {}) { - return this.execute("OPTIONS", url, options); - } - /** - * The 'HEAD' method performs a HEAD request to the provided URL with the provided options. - * - * @param url - The URL to perform the HEAD request to. - * @param options - The options for the HEAD request. - * - * @returns The response from the 'execute' method. - */ - head(url, options = {}) { - return this.execute("HEAD", url, options); - } - /** - * The 'POST' method performs a POST request to the provided URL with the provided options. - * - * @param url - The URL to perform the POST request to. - * @param options - The options for the POST request. - * - * @returns The response from the 'execute' method. - */ - post(url, options = {}) { - return this.execute("POST", url, options); - } - /** - * The 'PATCH' method performs a PATCH request to the provided URL with the provided options. - * - * @param url - The URL to perform the PATCH request to. - * @param options - The options for the PATCH request. - * - * @returns The response from the 'execute' method. - */ - patch(url, options = {}) { - return this.execute("PATCH", url, options); - } - /** - * The 'PUT' method performs a PUT request to the provided URL with the provided options. - * - * @param url - The URL to perform the PUT request to. - * @param options - The options for the PUT request. - * - * @returns The response from the 'execute' method. - */ - put(url, options = {}) { - return this.execute("PUT", url, options); - } - /** - * The 'close' method closes the current session. - * - * @returns The response from the 'destroySession' function. - */ - async close() { - return Client_1.Client.getInstance().pool?.run(JSON.stringify({ - sessionId: this.sessionId, - }), { name: "destroySession" }); - } - async execute(method, url, options = {}) { - const headers = options?.headers !== undefined - ? options.headers - : this.config.headers ?? this.getDefaultHeaders(); - const requestCookies = await this.jar.mergeCookies(options?.cookies || {}, url.toString()); - const payload = { - sessionId: this.sessionId, - followRedirects: options.followRedirects ?? false, - forceHttp1: this.config.forceHttp1 ?? false, - withDebug: this.config.debug ?? false, - headers, - headerOrder: options.headerOrder || this.config.headerOrder || [], - insecureSkipVerify: this.config.insecureSkipVerify ?? false, - proxyUrl: options.proxy || this.config.proxy || "", - isRotatingProxy: options?.isRotatingProxy ?? this.config.isRotatingProxy ?? false, - requestUrl: url, - requestMethod: method, - requestBody: options?.body || null, - timeoutMilliseconds: this.config.timeout || 0, - withRandomTLSExtensionOrder: this.config.randomTlsExtensionOrder ?? false, - isByteResponse: options?.byteResponse ?? false, - isByteRequest: (0, utils_1.isByteRequest)(headers), - requestHostOverride: options?.hostOverride || null, - disableIPV6: this.config.disableIPV6 ?? false, - disableIPV4: this.config.disableIPV4 ?? false, - transportOptions: this.config.transportOptions ?? undefined, - catchPanics: false, - streamOutputEOFSymbol: this.config.streamOutputEOFSymbol ?? null, - streamOutputPath: this.config.streamOutputPath ?? null, - streamOutputBlockSize: this.config.streamOutputBlockSize ?? null, - serverNameOverwrite: this.config.serverNameOverwrite ?? "", - connectHeaders: this.config.connectHeaders ?? options.connectHeaders ?? {}, - localAddress: this.config.localAddress ?? null, - withDefaultCookieJar: true, - withoutCookieJar: false, - requestCookies, - }; - if (this.config.clientIdentifier) { - payload["tlsClientIdentifier"] = this.config.clientIdentifier; - } - else if (this.config.ja3string) { - payload["customTlsClient"] = { - ja3String: this.config.ja3string, - h2Settings: this.config.h2Settings ?? {}, - h2SettingsOrder: this.config.h2SettingsOrder ?? [], - pseudoHeaderOrder: this.config.pseudoHeaderOrder ?? [], - connectionFlow: this.config.connectionFlow ?? 0, - priorityFrames: this.config.priorityFrames ?? [], - headerPriority: this.config.headerPriority ?? { - streamDep: 0, - exclusive: false, - weight: 0, - }, - certCompressionAlgo: this.config.certCompressionAlgo ?? "zlib", - supportedVersions: this.config.supportedVersions ?? [], - supportedSignatureAlgorithms: this.config.supportedSignatureAlgorithms ?? [], - keyShareCurves: this.config.keyShareCurves ?? [], - alpnProtocols: this.config.alpnProtocols ?? [], - alpsProtocols: this.config.alpsProtocols ?? [], - }; - } - else - payload["tlsClientIdentifier"] = interface_1.ClientIdentifier.chrome_131; - const requestPayloadString = JSON.stringify(payload); - const rawResponse = await Client_1.Client.getInstance().pool.run(requestPayloadString, { - name: "request", - }); - const response = JSON.parse(rawResponse); - const cookies = await this.jar.syncCookies(response.cookies || {}, url.toString()); - setImmediate(() => { - this.freeMemory(response.id).catch(() => { }); - }); - return new Response_1.Response({ ...response, cookies }); - } - async freeMemory(id) { - return Client_1.Client.getInstance().pool?.run(id.toString(), { - name: "freeMemory", - }); - } - getDefaultHeaders() { - return { - "User-Agent": `tls-client/${__version__}`, - "Accept-Encoding": "gzip, deflate, br", - Accept: "*/*", - Connection: "keep-alive", - }; - } -} -exports.Session = Session; diff --git a/dist/lib/index.js b/dist/lib/index.js deleted file mode 100644 index 8e1fcbb..0000000 --- a/dist/lib/index.js +++ /dev/null @@ -1,20 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -__exportStar(require("./Session"), exports); -__exportStar(require("./Response"), exports); -__exportStar(require("./requests"), exports); -__exportStar(require("./tlsClient"), exports); diff --git a/dist/lib/requests.js b/dist/lib/requests.js deleted file mode 100644 index b639a6d..0000000 --- a/dist/lib/requests.js +++ /dev/null @@ -1,52 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.fetch = fetch; -const _1 = require("."); -const utils_1 = require("../utils"); -/** - * Makes an HTTP request using the specified URL and options. - * - * @param {string} url - The URL to make the request to. - * @param {fetchOptions} [options] - Optional parameters for the request. - * @returns {Promise} The response from the HTTP request. - * @throws Will throw an error if the HTTP request fails or the method is not allowed. - */ -async function fetch(url, options) { - const session = new _1.Session(options?.options); - const method = options?.method?.toUpperCase() || "GET"; - try { - let response; - switch (method) { - case "GET": - response = await session.get(url, options); - break; - case "POST": - response = await session.post(url, options); - break; - case "PUT": - response = await session.put(url, options); - break; - case "DELETE": - response = await session.delete(url, options); - break; - case "HEAD": - response = await session.head(url, options); - break; - case "OPTIONS": - response = await session.options(url, options); - break; - case "PATCH": - response = await session.patch(url, options); - break; - default: - throw new Error(`HTTP method ${method} is not allowed.`); - } - return response; - } - catch (error) { - throw new utils_1.TlsClientError(error); - } - finally { - await session.close(); - } -} diff --git a/dist/lib/tlsClient.js b/dist/lib/tlsClient.js deleted file mode 100644 index 27da682..0000000 --- a/dist/lib/tlsClient.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.initTLS = initTLS; -exports.destroyTLS = destroyTLS; -const Client_1 = require("./Client"); -async function initTLS() { - return Client_1.Client.init(); -} -async function destroyTLS() { - return Client_1.Client.destroy(); -} diff --git a/dist/utils/download.js b/dist/utils/download.js deleted file mode 100644 index 6cbeade..0000000 --- a/dist/utils/download.js +++ /dev/null @@ -1,188 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.LibraryDownloader = void 0; -const logger_1 = require("./logger"); -const https_1 = __importDefault(require("https")); -const fs_1 = __importStar(require("fs")); -const readline = __importStar(require("readline")); -class LibraryDownloader { - static file; - static path; - static issueURL = "https://github.com/Sahil1337/node-tls-client/issues"; - static async retrieveLibrary(file, libPath) { - this.file = file; - this.path = libPath; - try { - const latest = await this.getLatest(); - if (latest) { - await this.extract(latest.browser_download_url); - logger_1.logger.success("Extracted shared library."); - return true; - } - else { - logger_1.logger.error(`Failed to find required asset: ${this.file.name}, report ${logger_1.logger.hyperlink("here", this.issueURL)}.`); - return false; - } - } - catch (error) { - logger_1.logger.error(`Initialization failed: ${error}`); - return false; - } - } - static formatBytes(bytes, decimals = 2) { - if (bytes === 0) - return "0 Bytes"; - const k = 1024; - const dm = decimals < 0 ? 0 : decimals; - const sizes = ["Bytes", "KB", "MB", "GB", "TB"]; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i]; - } - static progress(downloaded, total) { - const percentage = (downloaded / total) * 100; - const progress = Math.floor(percentage / 2); - const bar = "█".repeat(progress) + " ".repeat(50 - progress); - readline.clearLine(process.stdout, 0); - readline.cursorTo(process.stdout, 0); - process.stdout.write(`${logger_1.logger.stamp} DOWNLOADING:[${bar}] ${percentage.toFixed(2)}% (${this.formatBytes(downloaded)} / ${this.formatBytes(total)})`); - } - static async download(url, file) { - return new Promise((resolve, reject) => { - https_1.default - .get(url, (response) => { - if (response.statusCode && - response.statusCode >= 300 && - response.statusCode < 400 && - response.headers.location) { - const newURL = new URL(response.headers.location, url).toString(); - logger_1.logger.debug(`Fetched shared library ${logger_1.logger.hyperlink("url", newURL)}`); - this.download(newURL, file).then(resolve).catch(reject); - } - else if (response.statusCode && - response.statusCode >= 200 && - response.statusCode < 300) { - const totalBytes = parseInt(response.headers["content-length"] || "0", 10); - let downloadedBytes = 0; - response.pipe(file); - response.on("data", (chunk) => { - downloadedBytes += chunk.length; - this.progress(downloadedBytes, totalBytes); - }); - response.on("end", () => { - file.close((err) => { - if (err) { - reject(err); - } - else { - process.stdout.write("\n"); - resolve(); - } - }); - }); - file.on("error", (err) => { - fs_1.default.unlink(this.path, () => reject(err)); - }); - } - else { - logger_1.logger.error(`Failed to download the file [statusCode:${response.statusCode}]`); - reject(); - } - }) - .on("error", (err) => { - fs_1.default.unlink(this.path, () => reject(err)); - }); - }); - } - static async extract(url) { - return new Promise((resolve, reject) => { - const file = (0, fs_1.createWriteStream)(this.path); - this.download(url, file).then(resolve).catch(reject); - }); - } - static async getLatest() { - return new Promise((resolve) => { - const options = { - hostname: "api.github.com", - path: "/repos/bogdanfinn/tls-client/releases/latest", - method: "GET", - headers: { - "user-agent": "node-tls-client", - }, - }; - https_1.default - .get(options, (res) => { - let data = ""; - res.on("data", (chunk) => { - data += chunk; - }); - res.on("end", () => { - if (res.statusCode === 200) { - try { - const response = JSON.parse(data); - const version = response.tag_name.replace("v", ""); - logger_1.logger.debug(`Fetched latest version: v${version}`); - const assetName = this.file.downloadName.replace("{version}", version); - const asset = response.assets.find((asset) => asset.name === assetName); - if (!asset) { - logger_1.logger.error(`Failed to find required asset: ${this.file.name}, report ${logger_1.logger.hyperlink("here", this.issueURL)}.`); - resolve(null); - } - else { - resolve(asset); - } - } - catch (err) { - logger_1.logger.error(`Failed to parse response: ${err}`); - resolve(null); - } - } - else { - logger_1.logger.error(`Failed to fetch the latest version. Status code: ${res.statusCode}`); - resolve(null); - } - }); - }) - .on("error", (err) => { - logger_1.logger.error(`Failed to fetch the latest version: ${err}`); - resolve(null); - }); - }); - } -} -exports.LibraryDownloader = LibraryDownloader; diff --git a/dist/utils/index.js b/dist/utils/index.js deleted file mode 100644 index 555eb2e..0000000 --- a/dist/utils/index.js +++ /dev/null @@ -1,20 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -__exportStar(require("./download"), exports); -__exportStar(require("./logger"), exports); -__exportStar(require("./request"), exports); -__exportStar(require("./tlsError"), exports); diff --git a/dist/utils/logger.js b/dist/utils/logger.js deleted file mode 100644 index c8cdd3e..0000000 --- a/dist/utils/logger.js +++ /dev/null @@ -1,33 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.logger = void 0; -const colors = { - reset: "\x1b[0m", - blue: "\x1b[34m", - red: "\x1b[31m", - green: "\x1b[32m", - cyan: "\x1b[36m", -}; -/** - * Logger utility. - * - * @property {Function} debug - Logs a debug message. - * @property {Function} error - Logs an error message. - * @property {Function} success - Logs a success message. - * @property {Function} hyperlink - Generates a clickable hyperlink. - */ -exports.logger = { - debug: function (...args) { - return process.stdout.write(`${colors.cyan}@node-tls-client ~ ${colors.blue}DEBUG:${colors.reset} ${args.join(" ")}\n`); - }, - error: function (...args) { - return process.stdout.write(`${colors.cyan}@node-tls-client ~ ${colors.red}ERROR:${colors.reset} ${args.join(" ")}\n`); - }, - success: function (...args) { - return process.stdout.write(`${colors.cyan}@node-tls-client ~ ${colors.green}SUCCESS:${colors.reset} ${args.join(" ")}\n`); - }, - hyperlink: function (text, url) { - return `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\`; - }, - stamp: `${colors.cyan}@node-tls-client ~${colors.reset}`, -}; diff --git a/dist/utils/native.js b/dist/utils/native.js deleted file mode 100644 index 1ad6cf3..0000000 --- a/dist/utils/native.js +++ /dev/null @@ -1,79 +0,0 @@ -"use strict"; -/** - * Loads and handles functionality related to shared library management. - */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.LibraryHandler = void 0; -const path_1 = __importDefault(require("path")); -const promises_1 = __importDefault(require("fs/promises")); -const os_1 = __importDefault(require("os")); -const koffi_1 = require("koffi"); -const download_1 = require("./download"); -class LibraryHandler { - static path = path_1.default.join(os_1.default.tmpdir(), this.retrieveFileInfo().name); - static async validateFile() { - const fileExists = await promises_1.default - .access(this.path) - .then(() => true) - .catch(() => false); - if (!fileExists) { - const isDownloaded = await download_1.LibraryDownloader.retrieveLibrary(LibraryHandler.retrieveFileInfo(), LibraryHandler.path); - if (!isDownloaded) - return process.exit(1); - } - } - static retrieveLibrary() { - const library = (0, koffi_1.load)(LibraryHandler.path); - return { - request: library.func("request", "string", ["string"]), - freeMemory: library.func("freeMemory", "void", ["string"]), - destroyAll: library.func("destroyAll", "string", []), - destroySession: library.func("destroySession", "string", ["string"]), - }; - } - static retrieveFileInfo() { - const platform = process.platform; - const arch = process.arch; - const map = { - darwin: { - arm64: { - name: "tls-client-arm64.dylib", - downloadName: "tls-client-darwin-arm64-{version}.dylib", - }, - x64: { - name: "tls-client-x86.dylib", - downloadName: "tls-client-darwin-amd64-{version}.dylib", - }, - }, - win32: { - x64: { - name: "tls-client-64.dll", - downloadName: "tls-client-windows-64-{version}.dll", - }, - ia32: { - name: "tls-client-32.dll", - downloadName: "tls-client-windows-32-{version}.dll", - }, - }, - linux: { - arm64: { - name: "tls-client-arm64.so", - downloadName: "tls-client-linux-arm64-{version}.so", - }, - x64: { - name: "tls-client-x64.so", - downloadName: "tls-client-linux-ubuntu-amd64-{version}.so", - }, - default: { - name: "tls-client-amd64.so", - downloadName: "tls-client-linux-ubuntu-amd64-{version}.so", - }, - }, - }; - return map[platform]?.[arch] || map.linux.default; - } -} -exports.LibraryHandler = LibraryHandler; diff --git a/dist/utils/request.js b/dist/utils/request.js deleted file mode 100644 index 953490e..0000000 --- a/dist/utils/request.js +++ /dev/null @@ -1,55 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.isByteRequest = isByteRequest; -const exactContentTypes = new Set([ - "application/octet-stream", - "application/pdf", - "application/zip", - "application/gzip", - "application/x-rar-compressed", - "application/x-msdownload", - "application/x-sh", - "application/x-binary", - "base64", -]); -const prefixContentTypes = new Set([ - "image/", - "audio/", - "video/", - "application/vnd.", -]); -/** - * Determines if a request should be treated as a byte request based on its headers. - * - * This function checks the "Content-Type", "Content-Transfer-Encoding" and "Content-Encoding" headers - * to determine if the request is for binary data (such as images, audio, video, - * application binaries, etc.). If the headers indicate binary data, it returns true. - * - * @param {OutgoingHttpHeaders} headers - The headers of the request. - * @returns {boolean} - Returns true if the request is for binary data, otherwise false. - */ -function isByteRequest(headers) { - if (headers["content-encoding"] || headers["Content-Encoding"]) - return true; - const contentType = headers["content-type"] || headers["Content-Type"]; - const contentTransferEncoding = headers["content-transfer-encoding"] || - headers["Content-Transfer-Encoding"]; - if (contentTransferEncoding) { - const encodingString = String(contentTransferEncoding); - if (exactContentTypes.has(encodingString)) { - return true; - } - } - if (contentType) { - const contentTypeString = String(contentType); - if (exactContentTypes.has(contentTypeString)) { - return true; - } - for (const prefix of prefixContentTypes) { - if (contentTypeString.startsWith(prefix)) { - return true; - } - } - } - return false; -} diff --git a/dist/utils/tlsError.js b/dist/utils/tlsError.js deleted file mode 100644 index ec7c3a7..0000000 --- a/dist/utils/tlsError.js +++ /dev/null @@ -1,14 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.TlsClientError = void 0; -class TlsClientError extends Error { - constructor(message) { - super(message instanceof Error ? message.message : message); - if (message instanceof Error && message.stack) { - this.stack = message.stack; - } - this.name = "TlsClientError"; - Object.setPrototypeOf(this, new.target.prototype); - } -} -exports.TlsClientError = TlsClientError; diff --git a/dist/workers/index.js b/dist/workers/index.js deleted file mode 100644 index de101ae..0000000 --- a/dist/workers/index.js +++ /dev/null @@ -1,27 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.request = request; -exports.destroySession = destroySession; -exports.destroyAll = destroyAll; -exports.freeMemory = freeMemory; -const native_1 = require("../utils/native"); -const instance = native_1.LibraryHandler.retrieveLibrary(); -function request(payload) { - if (!payload) - return; - return instance.request(payload); -} -function destroySession(payload) { - if (!payload) - return; - return instance.destroySession(payload); -} -function destroyAll() { - return instance.destroyAll(); -} -function freeMemory(payload) { - if (!payload) - return; - return instance.freeMemory(payload); -} -exports.default = request; diff --git a/typings/index.d.ts b/typings/index.d.ts deleted file mode 100644 index 1bffbc6..0000000 --- a/typings/index.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./interface"; -export * from "./lib"; diff --git a/typings/interface/client.d.ts b/typings/interface/client.d.ts deleted file mode 100644 index 0a47340..0000000 --- a/typings/interface/client.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { KoffiFunction } from "koffi"; -export interface IClient { - request: KoffiFunction; - freeMemory: KoffiFunction; - destroyAll: KoffiFunction; - destroySession: KoffiFunction; -} diff --git a/typings/interface/index.d.ts b/typings/interface/index.d.ts deleted file mode 100644 index 10aefbd..0000000 --- a/typings/interface/index.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./session"; -export * from "./client"; diff --git a/typings/interface/native.d.ts b/typings/interface/native.d.ts deleted file mode 100644 index 402f0d3..0000000 --- a/typings/interface/native.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { KoffiFunction } from "koffi"; -export interface TlsNativeLibrary { - request: KoffiFunction; - freeMemory: KoffiFunction; - destroyAll: KoffiFunction; - destroySession: KoffiFunction; -} -type ArchMap = { - [arch: string]: FileInfo; -}; -export type FileInfo = { - name: string; - downloadName: string; -}; -export type PlatformMap = { - [platform: string]: ArchMap; -}; -export {}; diff --git a/typings/interface/payload.d.ts b/typings/interface/payload.d.ts deleted file mode 100644 index c31f8db..0000000 --- a/typings/interface/payload.d.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { OutgoingHttpHeaders } from "http2"; -import { CertCompressionAlgo, H2Settings, KeyShareCurves, Methods, PriorityFrames, PriorityParam, PseudoHeaderOrder, SupportedSignatureAlgorithms, SupportedVersions, TransportOptions } from "./session"; -export interface Payload { - catchPanics: boolean; - customTlsClient?: CustomTlsClient; - tlsClientIdentifier?: string; - transportOptions?: TransportOptions; - followRedirects: boolean; - forceHttp1: boolean; - headerOrder: OutgoingHttpHeaders[]; - headers: OutgoingHttpHeaders; - connectHeaders: Record; - insecureSkipVerify: boolean; - isByteRequest: boolean; - isByteResponse: boolean; - isRotatingProxy: boolean; - proxyUrl: string; - requestBody: string; - requestCookies: { - name: string; - value: string; - }[]; - requestHostOverride: string | null; - requestMethod: Methods; - requestUrl: string | URL; - disableIPV6: boolean; - disableIPV4: boolean; - localAddress: string | null; - sessionId: string; - serverNameOverwrite?: string; - streamOutputBlockSize?: number | null; - streamOutputEOFSymbol?: string | null; - streamOutputPath?: string | null; - timeoutMilliseconds: number; - withDebug: boolean; - withDefaultCookieJar: boolean; - withoutCookieJar: boolean; - withRandomTLSExtensionOrder: boolean; -} -interface CustomTlsClient { - ja3String: string; - h2Settings: H2Settings; - h2SettingsOrder: (keyof H2Settings)[]; - pseudoHeaderOrder: PseudoHeaderOrder[]; - connectionFlow: number; - priorityFrames: PriorityFrames[]; - headerPriority: PriorityParam; - certCompressionAlgo: CertCompressionAlgo; - supportedVersions: SupportedVersions[]; - supportedSignatureAlgorithms: SupportedSignatureAlgorithms[]; - keyShareCurves: KeyShareCurves[]; - alpnProtocols: string[]; - alpsProtocols: string[]; -} -export {}; diff --git a/typings/interface/session.d.ts b/typings/interface/session.d.ts deleted file mode 100644 index 015645e..0000000 --- a/typings/interface/session.d.ts +++ /dev/null @@ -1,493 +0,0 @@ -import { IncomingHttpHeaders, OutgoingHttpHeaders } from "http"; -/** - * Represents various settings for HTTP/2 (h2) protocol. - */ -export interface H2Settings { - /** - * The size of the header compression table used in HTTP/2. - */ - HEADER_TABLE_SIZE?: number; - /** - * Indicates whether server push is enabled in HTTP/2. - */ - ENABLE_PUSH?: boolean; - /** - * The maximum number of concurrent streams allowed in HTTP/2. - */ - MAX_CONCURRENT_STREAMS?: number; - /** - * The initial window size for HTTP/2 data frames. - */ - INITIAL_WINDOW_SIZE?: number; - /** - * The maximum size of HTTP/2 frames. - */ - MAX_FRAME_SIZE?: number; - /** - * The maximum size of header list in HTTP/2. - */ - MAX_HEADER_LIST_SIZE?: number; -} -/** - * Represents various supported signature algorithms for TLS. - */ -export type SupportedSignatureAlgorithms = "PKCS1WithSHA256" | "PKCS1WithSHA384" | "PKCS1WithSHA512" | "PSSWithSHA256" | "PSSWithSHA384" | "PSSWithSHA512" | "ECDSAWithP256AndSHA256" | "ECDSAWithP384AndSHA384" | "ECDSAWithP521AndSHA512" | "PKCS1WithSHA1" | "ECDSAWithSHA1" | "Ed25519"; -/** - * Represents various supported versions of TLS. - */ -export type SupportedVersions = "GREASE" | "1.3" | "1.2" | "1.1" | "1.0"; -/** - * Represents various supported elliptic curves for key exchange. - */ -export type KeyShareCurves = "GREASE" | "P256" | "P384" | "P521" | "X25519" | "P256Kyber768" | "X25519Kyber512D" | "X25519Kyber768"; -/** - * Represents various certificate compression algorithms. - */ -export type CertCompressionAlgo = "zlib" | "brotli" | "zstd"; -/** - * Represents parameters for setting priority of HTTP/2 streams. - */ -export interface PriorityParam { - /** - * The stream dependency for priority. - */ - streamDep: number; - /** - * Indicates whether the priority is exclusive. - */ - exclusive: boolean; - /** - * The weight of the priority. - */ - weight: number; -} -/** - * Represents priority frames for HTTP/2 streams. - */ -export interface PriorityFrames { - /** - * The stream ID for which priority is set. - */ - streamID: number; - /** - * The parameters for priority settings. - */ - priorityParam: PriorityParam; -} -/** - * Represents the order of pseudo headers in HTTP/2 requests. - */ -export type PseudoHeaderOrder = ":method" | ":authority" | ":scheme" | ":path"; -/** - * Represents various HTTP methods. - */ -export type Methods = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD"; -/** - * Represents various client identifiers. - * - * The client identifiers are grouped by browser, mobile clients, and other clients. - */ -export declare enum ClientIdentifier { - chrome_103 = "chrome_103", - chrome_104 = "chrome_104", - chrome_105 = "chrome_105", - chrome_106 = "chrome_106", - chrome_107 = "chrome_107", - chrome_108 = "chrome_108", - chrome_109 = "chrome_109", - chrome_110 = "chrome_110", - chrome_111 = "chrome_111", - chrome_112 = "chrome_112", - chrome_116_PSK = "chrome_116_PSK", - chrome_116_PSK_PQ = "chrome_116_PSK_PQ", - chrome_117 = "chrome_117", - chrome_120 = "chrome_120", - chrome_124 = "chrome_124", - chrome_131 = "chrome_131", - chrome_131_psk = "chrome_131_PSK", - safari_15_6_1 = "safari_15_6_1", - safari_16_0 = "safari_16_0", - safari_ipad_15_6 = "safari_ipad_15_6", - safari_ios_15_5 = "safari_ios_15_5", - safari_ios_15_6 = "safari_ios_15_6", - safari_ios_16_0 = "safari_ios_16_0", - safari_ios_17_0 = "safari_ios_17_0", - safari_ios_18_0 = "safari_ios_18_0", - firefox_102 = "firefox_102", - firefox_104 = "firefox_104", - firefox_105 = "firefox_105", - firefox_106 = "firefox_106", - firefox_108 = "firefox_108", - firefox_110 = "firefox_110", - firefox_117 = "firefox_117", - firefox_120 = "firefox_120", - firefox_123 = "firefox_123", - firefox_132 = "firefox_132", - firefox_133 = "firefox_133", - opera_89 = "opera_89", - opera_90 = "opera_90", - opera_91 = "opera_91", - zalando_android_mobile = "zalando_android_mobile", - zalando_ios_mobile = "zalando_ios_mobile", - nike_ios_mobile = "nike_ios_mobile", - nike_android_mobile = "nike_android_mobile", - cloudscraper = "cloudscraper", - mms_ios = "mms_ios", - mms_ios_1 = "mms_ios_1", - mms_ios_2 = "mms_ios_2", - mms_ios_3 = "mms_ios_3", - mesh_ios = "mesh_ios", - mesh_ios_1 = "mesh_ios_1", - mesh_ios_2 = "mesh_ios_2", - mesh_android = "mesh_android", - mesh_android_1 = "mesh_android_1", - mesh_android_2 = "mesh_android_2", - confirmed_ios = "confirmed_ios", - confirmed_android = "confirmed_android", - okhttp4_android_7 = "okhttp4_android_7", - okhttp4_android_8 = "okhttp4_android_8", - okhttp4_android_9 = "okhttp4_android_9", - okhttp4_android_10 = "okhttp4_android_10", - okhttp4_android_11 = "okhttp4_android_11", - okhttp4_android_12 = "okhttp4_android_12", - okhttp4_android_13 = "okhttp4_android_13" -} -/** - * Represents options for creating a session. - */ -export interface SessionOptions { - /** - * The unique identifier for the session. - */ - sessionId?: string; - /** - * The headers for the session. - */ - headers?: OutgoingHttpHeaders; - /** - * The headers for the connect request. - */ - connectHeaders?: Record; - /** - * The proxy server to use for the session. - */ - proxy?: string; - /** - * Whether the proxy is rotating proxy. - */ - isRotatingProxy?: boolean; - /** - * The client identifier for the session. - */ - clientIdentifier?: ClientIdentifier; - /** - * The JA3 string for the session. - */ - ja3string?: string; - /** - * The settings for HTTP/2. - */ - h2Settings?: H2Settings; - /** - * The order of HTTP/2 settings. - */ - h2SettingsOrder?: (keyof H2Settings)[]; - /** - * The supported signature algorithms. - */ - supportedSignatureAlgorithms?: SupportedSignatureAlgorithms[]; - /** - * The server name to overwrite. - */ - serverNameOverwrite?: string; - /** - * The block size for the stream output. - */ - streamOutputBlockSize?: number; - /** - * The symbol to use for the stream output. - */ - streamOutputEOFSymbol?: string; - /** - * The path for the stream output. - */ - streamOutputPath?: string; - /** - * The local address for the session. - */ - localAddress?: string; - /** - * The supported versions of TLS. - */ - supportedVersions?: SupportedVersions[]; - /** - * The supported elliptic curves for key exchange. - */ - keyShareCurves?: KeyShareCurves[]; - /** - * The certificate compression algorithm. - */ - certCompressionAlgo?: CertCompressionAlgo; - /** - * The order of pseudo headers. - */ - pseudoHeaderOrder?: PseudoHeaderOrder[]; - /** - * The connection flow for the session. - */ - connectionFlow?: number; - /** - * The transport options for the session. - */ - transportOptions?: TransportOptions; - /** - * The priority frames for HTTP/2 streams. - */ - priorityFrames?: PriorityFrames[]; - /** - * The order of headers. - */ - headerOrder?: OutgoingHttpHeaders[]; - /** - * The ALPN protocols. - */ - alpnProtocols?: string[]; - /** - * The ALPS protocols. - */ - alpsProtocols?: string[]; - /** - * The priority of headers. - */ - headerPriority?: PriorityParam; - /** - * Whether to randomize TLS extension order. - */ - randomTlsExtensionOrder?: boolean; - /** - * Whether to force HTTP/1 protocol. - */ - forceHttp1?: boolean; - /** - * Whether to enable debugging. - */ - debug?: boolean; - /** - * Whether to skip SSL certificate verification. - */ - insecureSkipVerify?: boolean; - /** - * The timeout duration for each request, in milliseconds. - */ - timeout?: number; - /** - * If true, IPv4 is disabled for the session requests. - */ - disableIPV4?: boolean; - /** - * If true, IPv6 is disabled for the session requests. - */ - disableIPV6?: boolean; -} -/** - * Represents base options for making HTTP requests, excluding the body. - */ -export interface BaseRequestOptions { - /** - * The headers for the request. - */ - headers?: OutgoingHttpHeaders; - /** - * The headers for the connect request. - */ - connectHeaders?: Record; - /** - * The order of headers. - */ - headerOrder?: OutgoingHttpHeaders[]; - /** - * Whether to follow redirects. - */ - followRedirects?: boolean; - /** - * The proxy server to use for the request. - */ - proxy?: string; - /** - * Whether proxy is rotating proxy or not. - */ - isRotatingProxy?: boolean; - /** - * Cookies for the request. - */ - cookies?: Record; - /** - * If true, indicates the response is in binary format, like base64-encoded images. - */ - byteResponse?: boolean; - /** - * Used to override the Host header, typically needed when making requests directly to an IP address. - */ - hostOverride?: string | null; -} -/** - * Transport-level options for HTTP requests. - * - * These options control connection reuse, compression, buffer sizes, and other low-level transport behaviors. - */ -export interface TransportOptions { - /** - * If true, disables HTTP keep-alive connections. - */ - disableKeepAlives: boolean; - /** - * If true, disables automatic response decompression (gzip, deflate, etc.). - */ - disableCompression: boolean; - /** - * The maximum number of idle (keep-alive) connections across all hosts. - */ - maxIdleConns: number; - /** - * The maximum number of idle (keep-alive) connections to keep per-host. - */ - maxIdleConnsPerHost: number; - /** - * The maximum number of total connections per host (idle + active). - */ - maxConnsPerHost: number; - /** - * The maximum number of bytes allowed in response headers. If zero, a default is used. - */ - maxResponseHeaderBytes: number; - /** - * The size of the write buffer in bytes. If zero, a default (typically 4KB) is used. - */ - writeBufferSize: number; - /** - * The size of the read buffer in bytes. If zero, a default (typically 4KB) is used. - */ - readBufferSize: number; - /** - * The maximum idle connection timeout, in nanoseconds. - */ - idleConnTimeout: number; -} -/** - * Represents options for making HTTP requests that may include a body. - */ -export interface RequestOptions extends BaseRequestOptions { - /** - * Request body. - */ - body?: any; -} -/** - * Represents options for making a GET HTTP request. - */ -export interface GetRequestOptions extends BaseRequestOptions { -} -/** - * Represents options for making a POST HTTP request. - */ -export interface PostRequestOptions extends RequestOptions { -} -/** - * Represents options for making a PUT HTTP request. - */ -export interface PutRequestOptions extends RequestOptions { -} -/** - * Represents options for making a DELETE HTTP request. - */ -export interface DeleteRequestOptions extends BaseRequestOptions { -} -/** - * Represents options for making a PATCH HTTP request. - */ -export interface PatchRequestOptions extends RequestOptions { -} -/** - * Represents options for making an OPTIONS HTTP request. - */ -export interface OptionsRequestOptions extends BaseRequestOptions { -} -/** - * Represents options for making a HEAD HTTP request. - */ -export interface HeadRequestOptions extends BaseRequestOptions { -} -/** - * Represents options for making HTTP requests. - */ -export interface fetchOptions { - /** - * Request method. - */ - method?: Methods; - /** - * The headers for the request. - */ - headers?: OutgoingHttpHeaders; - /** - * The body of the request. - */ - body?: any; - /** - * Whether to follow redirects. - */ - followRedirects?: boolean; - /** - * The proxy server to use for the request. - */ - proxy?: string; - /** - * Whether proxy is rotating proxy or not. - */ - isRotatingProxy?: boolean; - /** - * Cookies for the request. - */ - cookies?: Record; - /** - * Additional session options. - */ - options?: SessionOptions; -} -/** - * Represents a response from the shared library. - */ -export interface TlsResponse { - /** - * The unique identifier for the response. - */ - id: string; - /** - * The body of the response. - */ - body: string; - /** - * Cookies set in the response. - */ - cookies: Record; - /** - * Headers included in the response. - */ - headers: IncomingHttpHeaders; - /** - * The session ID associated with the response. - */ - sessionId: string; - /** - * The HTTP status code of the response. - */ - status: number; - /** - * The target URL of the response. - */ - target: string; - /** - * The protocol used for the response. - */ - usedProtocol: string; -} diff --git a/typings/lib/Client.d.ts b/typings/lib/Client.d.ts deleted file mode 100644 index 0293e6a..0000000 --- a/typings/lib/Client.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Piscina } from "piscina"; -export declare class Client { - private static instance; - private static ready; - private static readyPromise; - private _pool; - private constructor(); - static init(): Promise; - static destroy(): Promise; - static getInstance(): Client; - get pool(): Piscina; - static isReady(): boolean; -} diff --git a/typings/lib/Cookie.d.ts b/typings/lib/Cookie.d.ts deleted file mode 100644 index 889d2ac..0000000 --- a/typings/lib/Cookie.d.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { CookieJar } from "tough-cookie"; -export declare class Cookies extends CookieJar { - constructor(); - /** - * Fetches all cookies and organizes them by URL. - * - * This method serializes cookies and groups them by their domain and path, - * constructing a URL as the key and an object of cookies as key-value pairs. - * - * @returns A promise that resolves to an object where keys are URLs and values are objects containing cookies as key-value pairs. - */ - fetchAllCookies(): Promise; - /** - * Syncs cookies with the provided URL. - * - * @param cookies - An object containing cookies as key-value pairs. - * @param url - The URL for which cookies are to be set. - * @returns A promise that resolves to an object containing the synced cookies. - */ - syncCookies(cookies: Record, url: string): Promise>; - /** - * Merges the provided cookies with the existing cookies for a given URL according to request payload. - * - * @param cookies - An object containing cookies as key-value pairs. - * @param url - The URL for which cookies are to be set. - * @returns A promise that resolves to an array of objects, each containing the name and value of a cookie. - * - * @example - * mergeCookies({ 'cookie1': 'value1', 'cookie2': 'value2' }, 'http://example.com') - */ - mergeCookies(cookies: Record, url: string): Promise<{ - name: string; - value: string; - }[]>; -} diff --git a/typings/lib/Response.d.ts b/typings/lib/Response.d.ts deleted file mode 100644 index 6562841..0000000 --- a/typings/lib/Response.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TlsResponse } from "../interface"; -import { IncomingHttpHeaders } from "http"; -export declare class Response { - ok: boolean; - headers: IncomingHttpHeaders; - status: number; - url: string; - body: string; - cookies: Record; - constructor(response: TlsResponse); - /** - * Returns the body of the response as a string. - * - * @returns A promise that resolves with the body of the response as a string. - */ - text(): Promise; - /** - * Returns the body of the response as a JSON object. - * - * @typeparam T - The type of the JSON object. - * @returns A promise that resolves with the body of the response as a JSON object. - */ - json(): Promise; -} diff --git a/typings/lib/Session.d.ts b/typings/lib/Session.d.ts deleted file mode 100644 index 5014599..0000000 --- a/typings/lib/Session.d.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { DeleteRequestOptions, GetRequestOptions, HeadRequestOptions, Methods, OptionsRequestOptions, PatchRequestOptions, PostRequestOptions, PutRequestOptions, RequestOptions, SessionOptions } from "../interface"; -import { URL } from "url"; -import { Response } from "./Response"; -export declare class Session { - private readonly config; - private jar; - private sessionId; - constructor(config?: SessionOptions); - cookies(): Promise; - /** - * The 'GET' method performs a GET request to the provided URL with the provided options. - * - * @param url - The URL to perform the GET request to. - * @param options - The options for the GET request. - * - * @returns The response from the 'execute' method. - */ - get(url: string, options?: GetRequestOptions): Promise; - /** - * The 'DELETE' method performs a DELETE request to the provided URL with the provided options. - * - * @param url - The URL to perform the DELETE request to. - * @param options - The options for the DELETE request. - * - * @returns The response from the 'execute' method. - */ - delete(url: string, options?: DeleteRequestOptions): Promise; - /** - * The 'OPTIONS' method performs an OPTIONS request to the provided URL with the provided options. - * - * @param url - The URL to perform the OPTIONS request to. - * @param options - The options for the OPTIONS request. - * - * @returns The response from the 'execute' method. - */ - options(url: string, options?: OptionsRequestOptions): Promise; - /** - * The 'HEAD' method performs a HEAD request to the provided URL with the provided options. - * - * @param url - The URL to perform the HEAD request to. - * @param options - The options for the HEAD request. - * - * @returns The response from the 'execute' method. - */ - head(url: string, options?: HeadRequestOptions): Promise; - /** - * The 'POST' method performs a POST request to the provided URL with the provided options. - * - * @param url - The URL to perform the POST request to. - * @param options - The options for the POST request. - * - * @returns The response from the 'execute' method. - */ - post(url: string, options?: PostRequestOptions): Promise; - /** - * The 'PATCH' method performs a PATCH request to the provided URL with the provided options. - * - * @param url - The URL to perform the PATCH request to. - * @param options - The options for the PATCH request. - * - * @returns The response from the 'execute' method. - */ - patch(url: string, options?: PatchRequestOptions): Promise; - /** - * The 'PUT' method performs a PUT request to the provided URL with the provided options. - * - * @param url - The URL to perform the PUT request to. - * @param options - The options for the PUT request. - * - * @returns The response from the 'execute' method. - */ - put(url: string, options?: PutRequestOptions): Promise; - /** - * The 'close' method closes the current session. - * - * @returns The response from the 'destroySession' function. - */ - close(): Promise; - protected execute(method: Methods, url: string | URL, options?: RequestOptions): Promise; - private freeMemory; - private getDefaultHeaders; -} diff --git a/typings/lib/index.d.ts b/typings/lib/index.d.ts deleted file mode 100644 index 4326bdf..0000000 --- a/typings/lib/index.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./Session"; -export * from "./Response"; -export * from "./requests"; -export * from "./tlsClient"; diff --git a/typings/lib/requests.d.ts b/typings/lib/requests.d.ts deleted file mode 100644 index 2f2f79d..0000000 --- a/typings/lib/requests.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { fetchOptions } from "../interface"; -import { Response } from "."; -/** - * Makes an HTTP request using the specified URL and options. - * - * @param {string} url - The URL to make the request to. - * @param {fetchOptions} [options] - Optional parameters for the request. - * @returns {Promise} The response from the HTTP request. - * @throws Will throw an error if the HTTP request fails or the method is not allowed. - */ -export declare function fetch(url: string, options?: fetchOptions): Promise; diff --git a/typings/lib/tlsClient.d.ts b/typings/lib/tlsClient.d.ts deleted file mode 100644 index bc6d2ad..0000000 --- a/typings/lib/tlsClient.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export declare function initTLS(): Promise; -export declare function destroyTLS(): Promise; diff --git a/typings/utils/download.d.ts b/typings/utils/download.d.ts deleted file mode 100644 index b7d405d..0000000 --- a/typings/utils/download.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { FileInfo } from "../interface/native"; -export declare class LibraryDownloader { - private static file; - private static path; - private static readonly issueURL; - static retrieveLibrary(file: FileInfo, libPath: string): Promise; - private static formatBytes; - private static progress; - private static download; - private static extract; - private static getLatest; -} diff --git a/typings/utils/index.d.ts b/typings/utils/index.d.ts deleted file mode 100644 index 0a22cbd..0000000 --- a/typings/utils/index.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./download"; -export * from "./logger"; -export * from "./request"; -export * from "./tlsError"; diff --git a/typings/utils/logger.d.ts b/typings/utils/logger.d.ts deleted file mode 100644 index b5d47c9..0000000 --- a/typings/utils/logger.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Logger utility. - * - * @property {Function} debug - Logs a debug message. - * @property {Function} error - Logs an error message. - * @property {Function} success - Logs a success message. - * @property {Function} hyperlink - Generates a clickable hyperlink. - */ -export declare const logger: { - debug: (...args: any[]) => boolean; - error: (...args: any[]) => boolean; - success: (...args: any[]) => boolean; - hyperlink: (text: string, url: string) => string; - stamp: string; -}; diff --git a/typings/utils/native.d.ts b/typings/utils/native.d.ts deleted file mode 100644 index 8c8ecf6..0000000 --- a/typings/utils/native.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Loads and handles functionality related to shared library management. - */ -import { TlsNativeLibrary } from "../interface/native"; -export declare class LibraryHandler { - private static path; - static validateFile(): Promise; - static retrieveLibrary(): TlsNativeLibrary; - private static retrieveFileInfo; -} diff --git a/typings/utils/request.d.ts b/typings/utils/request.d.ts deleted file mode 100644 index 517d61e..0000000 --- a/typings/utils/request.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { OutgoingHttpHeaders } from "http"; -/** - * Determines if a request should be treated as a byte request based on its headers. - * - * This function checks the "Content-Type", "Content-Transfer-Encoding" and "Content-Encoding" headers - * to determine if the request is for binary data (such as images, audio, video, - * application binaries, etc.). If the headers indicate binary data, it returns true. - * - * @param {OutgoingHttpHeaders} headers - The headers of the request. - * @returns {boolean} - Returns true if the request is for binary data, otherwise false. - */ -export declare function isByteRequest(headers: OutgoingHttpHeaders): boolean; diff --git a/typings/utils/tlsError.d.ts b/typings/utils/tlsError.d.ts deleted file mode 100644 index 1581481..0000000 --- a/typings/utils/tlsError.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export declare class TlsClientError extends Error { - constructor(message: string | Error); -} diff --git a/typings/workers/index.d.ts b/typings/workers/index.d.ts deleted file mode 100644 index 5199cc7..0000000 --- a/typings/workers/index.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export declare function request(payload: string): any; -export declare function destroySession(payload: string): any; -export declare function destroyAll(): any; -export declare function freeMemory(payload: string): any; -export default request; From 868cfb4d553b70357dde55676727950ca539ecc1 Mon Sep 17 00:00:00 2001 From: Sahil1337 Date: Tue, 7 Jul 2026 12:20:39 +0530 Subject: [PATCH 2/2] chore: bump version to 2.2.0 and update dependencies feat: add support for multiple certificate compression algorithms - Changed `certCompressionAlgo` to `certCompressionAlgos` in payload and session interfaces. - Updated related documentation and examples. feat: introduce new session options - Added options for disabling HTTP/3, enabling protocol racing, and using custom cookie jars. - Added support for certificate pinning hosts and default headers. fix: update ClientIdentifier enum with new browser versions refactor: improve library handler to manage native binary versioning - Added version marker to ensure native binaries are re-downloaded when the wrapper version changes. chore: remove unused payload smoke test file build: update TypeScript configuration for better compatibility - Set root directory and added node types. --- .github/workflows/release.yml | 24 ++ .gitignore | 5 +- CHANGELOG.md | 60 ++- examples/http3.js | 51 +++ package-lock.json | 702 ++++++++++++++++++++++++++++++++++ package.json | 10 +- readme.md | 22 +- src/interface/payload.ts | 23 +- src/interface/session.ts | 169 +++++++- src/lib/Session.ts | 37 +- src/utils/native.ts | 30 +- tsconfig.json | 4 +- 12 files changed, 1110 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 examples/http3.js create mode 100644 package-lock.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..319319c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,24 @@ +name: Release + +on: + release: + types: [published] + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write # OIDC trusted publishing + steps: + # Pinned to commit SHA: a tag can be repointed by an attacker, a SHA cannot. + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + with: + node-version: 24 # ships npm >= 11.5.1, required for trusted publishing + registry-url: https://registry.npmjs.org + # --ignore-scripts: skip dependency lifecycle scripts (the postinstall-malware + # vector). tsc only needs type files, so the build still works without them. + - run: npm ci --ignore-scripts + - run: npm run build + - run: npm publish # auth via OIDC, provenance automatic diff --git a/.gitignore b/.gitignore index da71d95..6e9509a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ node_modules/ -*.lock \ No newline at end of file +*.lock +dist/ +typings/ +plans/* \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 0567701..2ed0723 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,40 @@ +# 2.2.0 (July 7, 2026) + +Syncs the wrapper to the native shared library **v1.15.1** (`RequestInput` parity). + +### Changes + +- **Default client profile is now `chrome_146`** (previously `chrome_131`), matching native's default. Applies only to sessions with no explicit `clientIdentifier` or `ja3string`. Pin `clientIdentifier: ClientIdentifier.chrome_131` to keep the old fingerprint. + +### Deprecations + +- **`certCompressionAlgo` (string) → `certCompressionAlgos` (array).** Prefer the new array key, e.g. `certCompressionAlgos: ["brotli"]`. The old singular key still works — a single value is wrapped into an array automatically — but is deprecated and will be removed in a future major. Default remains `["zlib"]`. + +### Additions + +- **New client profiles:** `chrome_130_psk`, `chrome_133(_psk)`, `chrome_144(_psk)`, `chrome_146(_psk)`, `brave_146(_psk)`, `safari_ios_18_5`, `safari_ios_26_0`, `firefox_135`, `firefox_146_psk`, `firefox_147(_psk)`, `firefox_148`. +- **New top-level SessionOptions:** `disableHttp3`, `withProtocolRacing`, `withoutCookieJar`, `withCustomCookieJar`, `certificatePinningHosts`, `defaultHeaders`, `timeoutSeconds`. +- **New custom-client (ja3string) options:** `h3Settings`, `h3SettingsOrder`, `h3PseudoHeaderOrder`, `h3PriorityParam`, `h3SendGreaseFrames`, `echCandidatePayloads`, `echCandidateCipherSuites`, `recordSizeLimit`, `streamId`, `allowHttp`, `supportedDelegatedCredentialsAlgorithms`. +- **New enum values:** `KeyShareCurves` gains `X25519Kyber768Old`, `X25519MLKEM768`; `SupportedSignatureAlgorithms` gains `SHA224_RSA`, `SHA224_ECDSA`. +- **HTTP/3 example:** [examples/http3.js](https://github.com/Sahil1337/node-tls-client/tree/main/examples/http3.js) + +### Fixes + +- Removed the dead `withDefaultCookieJar` payload field. Native's default (no jar flags) already provides a working cookie jar — cookie behavior is unchanged. +- **Cached native binary now refreshes on upgrade.** The shared library was cached under a version-agnostic filename and only re-downloaded when absent, so upgrading users kept a stale binary that lacked the new default profile (`chrome_146`) and rejected renamed fields. The cache is now keyed to the wrapper version via a marker file, forcing a one-time re-download after each upgrade. + +### Notes + +- The wrapper's own JS cookie jar is always active, so `withoutCookieJar` / `withCustomCookieJar` only affect native's per-request/redirect jar; cross-request cookie persistence still happens at the JS layer. +- Prefer `timeout` (ms) over `timeoutSeconds`; `timeoutMilliseconds` takes precedence natively when both are set. Do not set both. + # 2.1.0 (June 21, 2025) + > [!WARNING] > This version contains breaking changes. ### Breaking changes + - **TLS Client Initialization Requirement** The new method `initTLS()` **must be called before** using any session methods. You must also call `destroyTLS()` when the session is no longer needed. @@ -14,6 +46,7 @@ The `redirect` option in `requestOptions` is no longer supported. Use `followRedirects` instead. ### Additions/Fixes + - **Node.js Compatibility Fix** The `process.clearLine()` bug has been resolved. Fixed issues [#2](https://github.com/Sahil1337/node-tls-client/issues/2) , [#3](https://github.com/Sahil1337/node-tls-client/issues/3) , [#6](https://github.com/Sahil1337/node-tls-client/issues/6) @@ -34,7 +67,7 @@ - `streamOutputBlockSize` - `streamOutputEOFSymbol` - `streamOutputPath` - [Docs → SessionOptions](https://sahil1337.github.io/node-tls-client/interfaces/SessionOptions) + [Docs → SessionOptions](https://sahil1337.github.io/node-tls-client/interfaces/SessionOptions) - **Enhanced Documentation** Executable compatibility instructions and examples have been added to the documentation. [Instructions](https://github.com/Sahil1337/node-tls-client/tree/main/examples/samples/executable.md) @@ -43,21 +76,26 @@ Taking into account the `Content-Encoding` and `Content-Transfer-Encoding` headers to determine if the response is a byte response. [Accounting for pull request #8](https://github.com/Sahil1337/node-tls-client/pull/8) # 2.0.0 (December 15, 2024) + > [!WARNING] > This version contains breaking changes. + - Call `.init()` after setting up a session and before using any HTTP methods. (See the documentation for more details.) -- Resolved memory leak issues by moving to workerpool. -- Added new profiles: `chrome_131`, `chrome_131_psk`, `firefox_132`, `firefox_133`, and `ios_safari_18`. The default profile is now `chrome_131` (previously `chrome_124`). +- Resolved memory leak issues by moving to workerpool. +- Added new profiles: `chrome_131`, `chrome_131_psk`, `firefox_132`, `firefox_133`, and `ios_safari_18`. The default profile is now `chrome_131` (previously `chrome_124`). - Introduced the `isRotatingProxy` option for handling rotating proxies. PS: [SessionOptions](https://sahil1337.github.io/node-tls-client/interfaces/SessionOptions.html) # 1.1.4 (July 29, 2024) + > [!IMPORTANT] > This version includes significant updates and improvements. ### Breaking changes + - `response.cookies` is now a property instead of a method. [Note: `response.cookies()` has been removed and replaced with `response.cookies`.] ### Additional updates + - Added `session.cookies` property to retrieve all session cookies. For detailed information, see [examples/session-cookies.md](https://github.com/Sahil1337/node-tls-client/tree/main/examples/samples/cookie-example.md). - Added `byteResponse` option in requestOptions. Setting this to true ensures that the response is treated as a byte response. For detailed information, see [examples/images.js](https://github.com/Sahil1337/node-tls-client/tree/main/examples/images.js) - Added functionality to send binary data. Note: Ensure that the appropriate headers are set before sending binary data in the body. @@ -68,39 +106,55 @@ - Updated TlsResponse according to new changes. # 1.1.3 (June 13, 2024) + > [!WARNING] > This version contains breaking changes. ### Breaking changes + - `response.json()` and `response.text()` methods now return a `Promise`. - `response.cookies()` now returns an object of cookies instead of a`Promise`. - `session.methods` no longer include the `timeout` and `rejectUnauthorized` options. Since timeout cannot be changed during a session, ensure to specify `timeout` & `rejectUnauthorized` in SessionOptions when creating a session. ### Additions + - `fetch(fetchOptions)` method have been added to use different timeouts & rejectUnauthorized values in each request. [examples/timeout.js] for more information. ### Fixes + - Fixed a typo that prevented timeout from working correctly. # 1.1.2 (June 9, 2024) + ### Additions + - Introduced client profile types. + ### Changes + - Enhanced documentation for improved clarity and usability. - Updated the README with minor adjustments. - Refined interface definitions for better readability and understanding. # 1.1.1 (June 4 2024) + ### Additions + - Implemented dynamic methods for downloading shared files in "node-tls-client", eliminating the inclusion of prebuilt files. + ### Changes + - Path used for storing the shared library files is strictly set to tmpdir path. + ### Benefits + - Reduces package size. - Ensures better support for executables. # 1.1.0 (June 3, 2024) + ### Changes + - Improved handling of shared library files: - Only the shared library file matching the current operating system is preserved. All other shared library files are deleted. - Added support for executables. diff --git a/examples/http3.js b/examples/http3.js new file mode 100644 index 0000000..8b62f63 --- /dev/null +++ b/examples/http3.js @@ -0,0 +1,51 @@ +const { Session, ClientIdentifier, initTLS, destroyTLS } = require("node-tls-client"); + +/** + * @description Demonstrates HTTP/3 controls and new v1.15.1 parity options. + * `disableHttp3` / `withProtocolRacing` apply to every request; the `h3*` and + * ECH options only take effect on the ja3string path (inside customTlsClient). + * + * @see {@link https://sahil1337.github.io/node-tls-client/interfaces/SessionOptions.html SessionOptions} + */ +(async () => { + await initTLS(); + + // Top-level HTTP/3 controls (work with any clientIdentifier). + const session = new Session({ + clientIdentifier: ClientIdentifier.chrome_146, // new default profile + withProtocolRacing: true, // race HTTP/2 vs HTTP/3 + disableHttp3: false, + timeout: 30 * 1000, + }); + + // Custom-client (ja3) path — h3Settings uses named string keys. + const customSession = new Session({ + ja3string: + "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0", + h3Settings: { + QPACK_MAX_TABLE_CAPACITY: 65536, + MAX_FIELD_SECTION_SIZE: 262144, + QPACK_BLOCKED_STREAMS: 100, + }, + h3SettingsOrder: [ + "QPACK_MAX_TABLE_CAPACITY", + "MAX_FIELD_SECTION_SIZE", + "QPACK_BLOCKED_STREAMS", + ], + h3SendGreaseFrames: true, + }); + + try { + const r1 = await session.get("https://tls.peet.ws/api/all"); + console.log("default profile:", r1.status); + + const r2 = await customSession.get("https://tls.peet.ws/api/all"); + console.log("custom ja3:", r2.status); + } catch (error) { + console.error("An error occurred:", error); + } finally { + await session.close(); + await customSession.close(); + await destroyTLS(); + } +})(); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..4f32e12 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,702 @@ +{ + "name": "node-tls-client", + "version": "2.2.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "node-tls-client", + "version": "2.2.0", + "license": "GPL-3.0", + "dependencies": { + "cookie-parser": "^1.4.7", + "koffi": "^2.8.9", + "piscina": "^5.1.1", + "tough-cookie": "^4.1.4" + }, + "devDependencies": { + "@types/cookie-parser": "^1.4.9", + "@types/node": "^24.13.2", + "@types/tough-cookie": "^4.0.5", + "typedoc": "^0.25.13", + "typescript": "^6.0.3" + } + }, + "node_modules/@napi-rs/nice": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz", + "integrity": "sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/nice-android-arm-eabi": "1.1.1", + "@napi-rs/nice-android-arm64": "1.1.1", + "@napi-rs/nice-darwin-arm64": "1.1.1", + "@napi-rs/nice-darwin-x64": "1.1.1", + "@napi-rs/nice-freebsd-x64": "1.1.1", + "@napi-rs/nice-linux-arm-gnueabihf": "1.1.1", + "@napi-rs/nice-linux-arm64-gnu": "1.1.1", + "@napi-rs/nice-linux-arm64-musl": "1.1.1", + "@napi-rs/nice-linux-ppc64-gnu": "1.1.1", + "@napi-rs/nice-linux-riscv64-gnu": "1.1.1", + "@napi-rs/nice-linux-s390x-gnu": "1.1.1", + "@napi-rs/nice-linux-x64-gnu": "1.1.1", + "@napi-rs/nice-linux-x64-musl": "1.1.1", + "@napi-rs/nice-openharmony-arm64": "1.1.1", + "@napi-rs/nice-win32-arm64-msvc": "1.1.1", + "@napi-rs/nice-win32-ia32-msvc": "1.1.1", + "@napi-rs/nice-win32-x64-msvc": "1.1.1" + } + }, + "node_modules/@napi-rs/nice-android-arm-eabi": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.1.1.tgz", + "integrity": "sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-android-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.1.1.tgz", + "integrity": "sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-darwin-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.1.1.tgz", + "integrity": "sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-darwin-x64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.1.1.tgz", + "integrity": "sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-freebsd-x64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.1.1.tgz", + "integrity": "sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm-gnueabihf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.1.1.tgz", + "integrity": "sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.1.1.tgz", + "integrity": "sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm64-musl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.1.1.tgz", + "integrity": "sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-ppc64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.1.1.tgz", + "integrity": "sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-riscv64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.1.1.tgz", + "integrity": "sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-s390x-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.1.1.tgz", + "integrity": "sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-x64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.1.1.tgz", + "integrity": "sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-x64-musl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.1.1.tgz", + "integrity": "sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-openharmony-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-openharmony-arm64/-/nice-openharmony-arm64-1.1.1.tgz", + "integrity": "sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-arm64-msvc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.1.1.tgz", + "integrity": "sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-ia32-msvc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.1.1.tgz", + "integrity": "sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-x64-msvc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.1.1.tgz", + "integrity": "sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie-parser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.10.tgz", + "integrity": "sha512-B4xqkqfZ8Wek+rCOeRxsjMS9OgvzebEzzLYw7NHYuvzb7IdxOkI0ZHGgeEBX4PUM7QGVvNSK60T3OvWj3YfBRg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/express": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz", + "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "^2" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz", + "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.13.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.2.tgz", + "integrity": "sha512-fRa09kZTgu8o71KFcDjUFuc7F+dEbZYZmkI0mg5YBTRs0yMKjYHsq/c0urDKeDb+D5qVgXOdFcuu+DZPKOITwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*" + } + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.3.tgz", + "integrity": "sha512-+fksAx9eG3Ab6LDnLs3ZqZa8KVJ/jYnX+D4Qe1azX+LFGFAXqynCQLOdLpNYN/l9e7l6hMWwZbrnctqr6eSQSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/koffi": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/koffi/-/koffi-2.16.2.tgz", + "integrity": "sha512-owU0MRwv6xkrVqCd+33uw6BaYppkTRXbO/rVdJNI2dvZG0gzyRhYwW25eWtc5pauwK8TGh3AbkFONSezdykfSA==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "url": "https://liberapay.com/Koromix" + } + }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/piscina": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.2.0.tgz", + "integrity": "sha512-DszUCKeVN/5G5QKo6jAVHL8fmKnkJvQ0ACiVgY7YGCq3TUB2oznAOayvZPIAdEThvhczkXR+qm3IHsNXpFCYfA==", + "license": "MIT", + "engines": { + "node": ">=20.x" + }, + "optionalDependencies": { + "@napi-rs/nice": "^1.0.4" + } + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/shiki": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/typedoc": { + "version": "0.25.13", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.13.tgz", + "integrity": "sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.3", + "shiki": "^0.14.7" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/package.json b/package.json index bf77c97..127dcaa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-tls-client", - "version": "2.1.0", + "version": "2.2.0", "description": "Advanced library based on node-fetch and tls-client.", "main": "dist/index.js", "typings": "typings/index.d.ts", @@ -10,6 +10,8 @@ "private": false, "scripts": { "build": "tsc", + "prepare": "npm run build", + "prepublishOnly": "npm run build && npm run docs", "docs": "typedoc --out docs src/index.ts" }, "keywords": [ @@ -22,11 +24,11 @@ "cloudflare" ], "devDependencies": { - "@types/node": "^20.12.12", - "@types/tough-cookie": "^4.0.5", "@types/cookie-parser": "^1.4.9", + "@types/node": "^24.13.2", + "@types/tough-cookie": "^4.0.5", "typedoc": "^0.25.13", - "typescript": "^5.4.5" + "typescript": "^6.0.3" }, "dependencies": { "cookie-parser": "^1.4.7", diff --git a/readme.md b/readme.md index 51980cf..59546ee 100644 --- a/readme.md +++ b/readme.md @@ -117,7 +117,7 @@ const { Session, initTLS, destroyTLS } = require("node-tls-client"); alpsProtocols: ["h2"], supportedVersions: ["GREASE", "1.3", "1.2"], keyShareCurves: ["GREASE", "X25519"], - certCompressionAlgo: "brotli", + certCompressionAlgos: ["brotli"], pseudoHeaderOrder: [":method", ":authority", ":scheme", ":path"], connectionFlow: 15663105, headerOrder: ["accept", "user-agent", "accept-encoding", "accept-language"], @@ -201,7 +201,7 @@ const { Session, ClientIdentifier, initTLS, destroyTLS } = require("node-tls-cli | `supportedSignatureAlgorithms` | [supportedSignatureAlgorithms](https://sahil1337.github.io/node-tls-client/types/SupportedSignatureAlgorithms.html)[] | An array of supported signature algorithms. | | `supportedVersions` | [supportedVersions](https://sahil1337.github.io/node-tls-client/types/SupportedVersions.html)[] | An array of supported TLS versions. | | `keyShareCurves` | [keyShareCurves](https://sahil1337.github.io/node-tls-client/types/KeyShareCurves.html)[] | An array of key share curves. | -| `certCompressionAlgo` | [certCompressionAlgo](https://sahil1337.github.io/node-tls-client/types/CertCompressionAlgo.html) | A certificate compression algorithm, e.g., `"brotli"`. | +| `certCompressionAlgos` | [certCompressionAlgo](https://sahil1337.github.io/node-tls-client/types/CertCompressionAlgo.html)[] | An array of certificate compression algorithms, e.g., `["brotli"]`. | | `pseudoHeaderOrder` | [pseudoHeaderOrder](https://sahil1337.github.io/node-tls-client/types/PseudoHeaderOrder.html)[] | An array specifying the order of pseudo-headers. | | `connectionFlow` | number | A number specifying the connection flow control window size. | | `priorityFrames` | [priorityFrame](https://sahil1337.github.io/node-tls-client/interfaces/PriorityFrames.html)[] | An array of priority frames to send with the request. | @@ -213,6 +213,24 @@ const { Session, ClientIdentifier, initTLS, destroyTLS } = require("node-tls-cli | `forceHttp1` | boolean | A boolean indicating whether to force the use of HTTP/1.1. | | `debug` | boolean | A boolean indicating whether to enable debug mode. | | `insecureSkipVerify` | boolean | A boolean indicating whether to skip SSL certificate verification. | +| `disableHttp3` | boolean | Disables HTTP/3 (QUIC) for the session. | +| `withProtocolRacing` | boolean | Enables protocol racing between HTTP/2 and HTTP/3. | +| `withoutCookieJar` | boolean | Disables native's per-request cookie jar. (The wrapper's own JS cookie jar stays active regardless.) | +| `withCustomCookieJar` | boolean | Uses a custom native cookie jar. (The wrapper's own JS cookie jar stays active regardless.) | +| `certificatePinningHosts` | Record | Maps a host to an array of pinned certificate fingerprints. | +| `defaultHeaders` | Record | Fallback headers, applied natively only for headers not already set (largely inert since the wrapper always sends a full header map). | +| `timeoutSeconds` | number | Request timeout in seconds. Prefer `timeout` (ms), which takes precedence natively — do not set both. | +| `h3Settings` | [H3Settings](https://sahil1337.github.io/node-tls-client/interfaces/H3Settings.html) | HTTP/3 settings (ja3string path only). | +| `h3SettingsOrder` | (keyof H3Settings)[] | Order of HTTP/3 settings (ja3string path only). | +| `h3PseudoHeaderOrder` | [pseudoHeaderOrder](https://sahil1337.github.io/node-tls-client/types/PseudoHeaderOrder.html)[] | Order of HTTP/3 pseudo-headers (ja3string path only). | +| `h3PriorityParam` | number | HTTP/3 priority param (ja3string path only). | +| `h3SendGreaseFrames` | boolean | Send HTTP/3 grease frames (ja3string path only). | +| `echCandidatePayloads` | number[] | ECH candidate payloads (ja3string path only). | +| `echCandidateCipherSuites` | [CandidateCipherSuite](https://sahil1337.github.io/node-tls-client/interfaces/CandidateCipherSuite.html)[] | ECH candidate cipher suites (ja3string path only). | +| `recordSizeLimit` | number | TLS record size limit (ja3string path only). | +| `streamId` | number | Stream ID (ja3string path only). | +| `allowHttp` | boolean | Allow plain HTTP (ja3string path only). | +| `supportedDelegatedCredentialsAlgorithms` | [supportedSignatureAlgorithms](https://sahil1337.github.io/node-tls-client/types/SupportedSignatureAlgorithms.html)[] | Supported delegated credentials algorithms (ja3string path only). | diff --git a/src/interface/payload.ts b/src/interface/payload.ts index 6a261cb..e8a600b 100644 --- a/src/interface/payload.ts +++ b/src/interface/payload.ts @@ -1,12 +1,15 @@ import { OutgoingHttpHeaders } from "http2"; import { + CandidateCipherSuite, CertCompressionAlgo, H2Settings, + H3Settings, KeyShareCurves, Methods, PriorityFrames, PriorityParam, PseudoHeaderOrder, + SupportedDelegatedCredentialsAlgorithms, SupportedSignatureAlgorithms, SupportedVersions, TransportOptions, @@ -41,10 +44,15 @@ export interface Payload { streamOutputEOFSymbol?: string | null; streamOutputPath?: string | null; timeoutMilliseconds: number; + timeoutSeconds?: number; withDebug: boolean; - withDefaultCookieJar: boolean; withoutCookieJar: boolean; + withCustomCookieJar: boolean; withRandomTLSExtensionOrder: boolean; + disableHttp3: boolean; + withProtocolRacing: boolean; + certificatePinningHosts?: Record; + defaultHeaders?: Record; } interface CustomTlsClient { @@ -55,10 +63,21 @@ interface CustomTlsClient { connectionFlow: number; priorityFrames: PriorityFrames[]; headerPriority: PriorityParam; - certCompressionAlgo: CertCompressionAlgo; + certCompressionAlgos: CertCompressionAlgo[]; supportedVersions: SupportedVersions[]; supportedSignatureAlgorithms: SupportedSignatureAlgorithms[]; + supportedDelegatedCredentialsAlgorithms: SupportedDelegatedCredentialsAlgorithms[]; keyShareCurves: KeyShareCurves[]; alpnProtocols: string[]; alpsProtocols: string[]; + h3Settings: H3Settings; + h3SettingsOrder: (keyof H3Settings)[]; + h3PseudoHeaderOrder: PseudoHeaderOrder[]; + h3PriorityParam: number; + h3SendGreaseFrames: boolean; + ECHCandidatePayloads: number[]; + ECHCandidateCipherSuites: CandidateCipherSuite[]; + recordSizeLimit: number; + streamId: number; + allowHttp: boolean; } diff --git a/src/interface/session.ts b/src/interface/session.ts index 826b720..5e03cca 100644 --- a/src/interface/session.ts +++ b/src/interface/session.ts @@ -48,10 +48,19 @@ export type SupportedSignatureAlgorithms = | "ECDSAWithP256AndSHA256" | "ECDSAWithP384AndSHA384" | "ECDSAWithP521AndSHA512" + | "SHA224_RSA" + | "SHA224_ECDSA" | "PKCS1WithSHA1" | "ECDSAWithSHA1" | "Ed25519"; +/** + * Represents supported delegated credentials algorithms for TLS. + * Same value space as {@link SupportedSignatureAlgorithms}. + */ +export type SupportedDelegatedCredentialsAlgorithms = + SupportedSignatureAlgorithms; + /** * Represents various supported versions of TLS. */ @@ -68,13 +77,47 @@ export type KeyShareCurves = | "X25519" | "P256Kyber768" | "X25519Kyber512D" - | "X25519Kyber768"; + | "X25519Kyber768" + | "X25519Kyber768Old" + | "X25519MLKEM768"; /** * Represents various certificate compression algorithms. */ export type CertCompressionAlgo = "zlib" | "brotli" | "zstd"; +/** + * Represents HTTP/3 (h3) protocol settings. Keys mirror the native string-keyed + * `H3SettingsMap` — do NOT use the uint-keyed `http3Settings` form. + */ +export interface H3Settings { + QPACK_MAX_TABLE_CAPACITY?: number; + MAX_FIELD_SECTION_SIZE?: number; + QPACK_BLOCKED_STREAMS?: number; + H3_DATAGRAM?: number; +} + +/** + * ECH HPKE key derivation function identifiers. + */ +export type KdfId = "HKDF_SHA256" | "HKDF_SHA384" | "HKDF_SHA512"; + +/** + * ECH HPKE AEAD identifiers. + */ +export type AeadId = + | "AEAD_AES_128_GCM" + | "AEAD_AES_256_GCM" + | "AEAD_CHACHA20_POLY1305"; + +/** + * A candidate cipher suite for Encrypted Client Hello (ECH). + */ +export interface CandidateCipherSuite { + kdfId: KdfId; + aeadId: AeadId; +} + /** * Represents parameters for setting priority of HTTP/2 streams. */ @@ -148,6 +191,17 @@ export enum ClientIdentifier { chrome_124 = "chrome_124", chrome_131 = "chrome_131", chrome_131_psk = "chrome_131_PSK", + chrome_130_psk = "chrome_130_PSK", + chrome_133 = "chrome_133", + chrome_133_psk = "chrome_133_PSK", + chrome_144 = "chrome_144", + chrome_144_psk = "chrome_144_PSK", + chrome_146 = "chrome_146", + chrome_146_psk = "chrome_146_PSK", + + // Brave versions + brave_146 = "brave_146", + brave_146_psk = "brave_146_PSK", // Safari versions safari_15_6_1 = "safari_15_6_1", @@ -158,6 +212,8 @@ export enum ClientIdentifier { safari_ios_16_0 = "safari_ios_16_0", safari_ios_17_0 = "safari_ios_17_0", safari_ios_18_0 = "safari_ios_18_0", + safari_ios_18_5 = "safari_ios_18_5", + safari_ios_26_0 = "safari_ios_26_0", // Firefox versions firefox_102 = "firefox_102", @@ -171,6 +227,11 @@ export enum ClientIdentifier { firefox_123 = "firefox_123", firefox_132 = "firefox_132", firefox_133 = "firefox_133", + firefox_135 = "firefox_135", + firefox_146_psk = "firefox_146_PSK", + firefox_147 = "firefox_147", + firefox_147_psk = "firefox_147_PSK", + firefox_148 = "firefox_148", // Opera versions opera_89 = "opera_89", @@ -306,7 +367,13 @@ export interface SessionOptions { keyShareCurves?: KeyShareCurves[]; /** - * The certificate compression algorithm. + * The certificate compression algorithms. + */ + certCompressionAlgos?: CertCompressionAlgo[]; + + /** + * @deprecated Use `certCompressionAlgos` (array) instead. Kept for backward + * compatibility — a single value is wrapped into an array automatically. */ certCompressionAlgo?: CertCompressionAlgo; @@ -384,6 +451,104 @@ export interface SessionOptions { * If true, IPv6 is disabled for the session requests. */ disableIPV6?: boolean; + + /** + * If true, disables HTTP/3 (QUIC) for the session requests. + */ + disableHttp3?: boolean; + + /** + * If true, enables protocol racing (HTTP/2 vs HTTP/3). + */ + withProtocolRacing?: boolean; + + /** + * If true, uses a custom cookie jar natively. Note: the wrapper's own JS + * cookie jar stays active regardless of this flag. + */ + withCustomCookieJar?: boolean; + + /** + * If true, disables the native per-request/redirect cookie jar. Note: the + * wrapper's own JS cookie jar stays active regardless of this flag, so + * cross-request cookie persistence still occurs at the JS layer. + */ + withoutCookieJar?: boolean; + + /** + * Certificate pinning hosts, mapping a host to an array of pinned + * certificate fingerprints. + */ + certificatePinningHosts?: Record; + + /** + * Default headers applied natively only as a fallback for headers not + * already set. Largely inert in this wrapper since a fully-populated header + * map is always sent. + */ + defaultHeaders?: Record; + + /** + * The timeout duration for each request, in seconds. Exposed for parity; + * prefer `timeout` (ms), which takes precedence natively. Do not set both. + */ + timeoutSeconds?: number; + + /** + * HTTP/3 settings. Only applied on the custom-client (ja3string) path. + */ + h3Settings?: H3Settings; + + /** + * The order of HTTP/3 settings. Only applied on the ja3string path. + */ + h3SettingsOrder?: (keyof H3Settings)[]; + + /** + * The order of HTTP/3 pseudo headers. Only applied on the ja3string path. + */ + h3PseudoHeaderOrder?: PseudoHeaderOrder[]; + + /** + * The HTTP/3 priority param. Only applied on the ja3string path. + */ + h3PriorityParam?: number; + + /** + * Whether to send HTTP/3 grease frames. Only applied on the ja3string path. + */ + h3SendGreaseFrames?: boolean; + + /** + * ECH candidate payloads. Only applied on the ja3string path. + */ + echCandidatePayloads?: number[]; + + /** + * ECH candidate cipher suites. Only applied on the ja3string path. + */ + echCandidateCipherSuites?: CandidateCipherSuite[]; + + /** + * The TLS record size limit. Only applied on the ja3string path. + */ + recordSizeLimit?: number; + + /** + * The stream ID. Only applied on the ja3string path. + */ + streamId?: number; + + /** + * Whether to allow plain HTTP. Only applied on the ja3string path. + */ + allowHttp?: boolean; + + /** + * The supported delegated credentials algorithms. Only applied on the + * ja3string path. + */ + supportedDelegatedCredentialsAlgorithms?: SupportedDelegatedCredentialsAlgorithms[]; } /** diff --git a/src/lib/Session.ts b/src/lib/Session.ts index 044dca6..2107561 100644 --- a/src/lib/Session.ts +++ b/src/lib/Session.ts @@ -21,7 +21,7 @@ import { Payload } from "../interface/payload"; import { Client } from "./Client"; import { Response } from "./Response"; -const __version__ = "2.1.0"; +const __version__ = "2.2.0"; export class Session { private jar = new Cookies(); @@ -176,11 +176,22 @@ export class Session { connectHeaders: this.config.connectHeaders ?? options.connectHeaders ?? {}, localAddress: this.config.localAddress ?? null, - withDefaultCookieJar: true, - withoutCookieJar: false, + withoutCookieJar: this.config.withoutCookieJar ?? false, + withCustomCookieJar: this.config.withCustomCookieJar ?? false, + disableHttp3: this.config.disableHttp3 ?? false, + withProtocolRacing: this.config.withProtocolRacing ?? false, requestCookies, }; + // Optional top-level fields: omit when unset so JSON.stringify drops them + // and native falls back to its zero-value behavior. + if (this.config.certificatePinningHosts !== undefined) + payload.certificatePinningHosts = this.config.certificatePinningHosts; + if (this.config.defaultHeaders !== undefined) + payload.defaultHeaders = this.config.defaultHeaders; + if (this.config.timeoutSeconds !== undefined) + payload.timeoutSeconds = this.config.timeoutSeconds; + if (this.config.clientIdentifier) { payload["tlsClientIdentifier"] = this.config.clientIdentifier; } else if (this.config.ja3string) { @@ -196,15 +207,31 @@ export class Session { exclusive: false, weight: 0, }, - certCompressionAlgo: this.config.certCompressionAlgo ?? "zlib", + certCompressionAlgos: + this.config.certCompressionAlgos ?? + (this.config.certCompressionAlgo + ? [this.config.certCompressionAlgo] + : ["zlib"]), supportedVersions: this.config.supportedVersions ?? [], supportedSignatureAlgorithms: this.config.supportedSignatureAlgorithms ?? [], + supportedDelegatedCredentialsAlgorithms: + this.config.supportedDelegatedCredentialsAlgorithms ?? [], keyShareCurves: this.config.keyShareCurves ?? [], alpnProtocols: this.config.alpnProtocols ?? [], alpsProtocols: this.config.alpsProtocols ?? [], + h3Settings: this.config.h3Settings ?? {}, + h3SettingsOrder: this.config.h3SettingsOrder ?? [], + h3PseudoHeaderOrder: this.config.h3PseudoHeaderOrder ?? [], + h3PriorityParam: this.config.h3PriorityParam ?? 0, + h3SendGreaseFrames: this.config.h3SendGreaseFrames ?? false, + ECHCandidatePayloads: this.config.echCandidatePayloads ?? [], + ECHCandidateCipherSuites: this.config.echCandidateCipherSuites ?? [], + recordSizeLimit: this.config.recordSizeLimit ?? 0, + streamId: this.config.streamId ?? 0, + allowHttp: this.config.allowHttp ?? false, }; - } else payload["tlsClientIdentifier"] = ClientIdentifier.chrome_131; + } else payload["tlsClientIdentifier"] = ClientIdentifier.chrome_146; const requestPayloadString = JSON.stringify(payload); diff --git a/src/utils/native.ts b/src/utils/native.ts index 70d4f86..581e0be 100644 --- a/src/utils/native.ts +++ b/src/utils/native.ts @@ -9,8 +9,14 @@ import os from "os"; import { load as koffi } from "koffi"; import { LibraryDownloader } from "./download"; +// Wrapper package version — the cached native binary is keyed to it so that +// upgrading node-tls-client forces a one-time re-download (a new wrapper release +// may require a newer native binary with new profiles/payload fields). +const packageVersion: string = require("../../package.json").version; + export class LibraryHandler { private static path = path.join(os.tmpdir(), this.retrieveFileInfo().name); + private static markerPath = LibraryHandler.path + ".version"; static async validateFile(): Promise { const fileExists = await fs @@ -18,14 +24,24 @@ export class LibraryHandler { .then(() => true) .catch(() => false); - if (!fileExists) { - const isDownloaded = await LibraryDownloader.retrieveLibrary( - LibraryHandler.retrieveFileInfo(), - LibraryHandler.path - ); + const marker = await fs + .readFile(this.markerPath, "utf8") + .then((v) => v.trim()) + .catch(() => null); + + // Re-download when the binary is missing, or when it was fetched for an + // older wrapper version (stale cache would lack newer client profiles / + // reject renamed payload fields). + if (fileExists && marker === packageVersion) return; + + const isDownloaded = await LibraryDownloader.retrieveLibrary( + LibraryHandler.retrieveFileInfo(), + LibraryHandler.path, + ); + + if (!isDownloaded) return process.exit(1); - if (!isDownloaded) return process.exit(1); - } + await fs.writeFile(this.markerPath, packageVersion).catch(() => {}); } static retrieveLibrary(): TlsNativeLibrary { diff --git a/tsconfig.json b/tsconfig.json index 5d0821c..36e2351 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,12 +4,14 @@ "experimentalDecorators": true, "emitDecoratorMetadata": true, "declaration": true, + "rootDir": "./src", "outDir": "./dist", "declarationDir": "./typings", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true, - "module": "commonjs" + "module": "commonjs", + "types": ["node"] } }