node-tls-client-kgb
Version:
Advanced library based on node-fetch and tls-client.
437 lines (436 loc) • 16.5 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Session = void 0;
const crypto_1 = require("crypto");
const session_1 = require("../interface/session");
const utils_1 = require("../utils");
const decorators_1 = require("../decorators");
const _1 = require(".");
const workerpool_1 = __importDefault(require("workerpool"));
const tough_cookie_1 = require("tough-cookie");
const __version__ = "1.0.0";
class Session {
sessionId;
proxy;
isRotatingProxy;
clientIdentifier;
ja3string;
h2Settings;
h2SettingsOrder;
supportedSignatureAlgorithms;
supportedVersions;
keyShareCurves;
certCompressionAlgo;
pseudoHeaderOrder;
connectionFlow;
priorityFrames;
headerOrder;
headerPriority;
randomTlsExtensionOrder;
forceHttp1;
debug;
insecureSkipVerify;
headers;
alpnProtocols;
alpsProtocols;
timeout;
disableIPV6;
disableIPV4;
jar = new _1.Cookies();
pool;
isReady = false;
constructor(options) {
this.sessionId = (0, crypto_1.randomUUID)();
this.proxy = options?.proxy || null;
this.isRotatingProxy = options?.isRotatingProxy ?? false;
this.alpnProtocols = options?.alpnProtocols || ["h2", "http/1.1"];
this.alpsProtocols = options?.alpsProtocols || ["http/1.1"];
this.headers = options?.headers || {
"User-Agent": `tls-client/${__version__}`,
"Accept-Encoding": "gzip, deflate, br",
Accept: "*/*",
Connection: "keep-alive",
};
this.clientIdentifier = options?.clientIdentifier;
this.ja3string = options?.ja3string;
this.h2Settings = options?.h2Settings;
this.h2SettingsOrder = options?.h2SettingsOrder;
this.supportedSignatureAlgorithms = options?.supportedSignatureAlgorithms;
this.supportedVersions = options?.supportedVersions;
this.keyShareCurves = options?.keyShareCurves;
this.certCompressionAlgo = options?.certCompressionAlgo;
this.headerOrder = options?.headerOrder;
this.pseudoHeaderOrder = options?.pseudoHeaderOrder;
this.connectionFlow = options?.connectionFlow;
this.priorityFrames = options?.priorityFrames;
this.headerPriority = options?.headerPriority;
this.randomTlsExtensionOrder = options?.randomTlsExtensionOrder || false;
this.forceHttp1 = options?.forceHttp1 || false;
this.debug = options?.debug || false;
this.insecureSkipVerify = options?.insecureSkipVerify || false;
this.timeout = options?.timeout || 30 * 1000;
this.disableIPV4 = options?.disableIPV4 ?? false;
this.disableIPV6 = options?.disableIPV6 ?? false;
}
async init() {
if (this.isReady)
return true;
try {
if (!this.pool) {
this.pool = workerpool_1.default.pool(require.resolve("../utils/worker"));
}
this.isReady = true;
return true;
}
catch (error) {
console.error("Initialization error:", error);
throw new utils_1.TlsClientError(error);
}
}
/**
* Retrieves all cookies from the jar.
*
* @returns An object where keys are URLs and values are objects containing cookies as key-value pairs.
*
* @example
{
"https://example.com/": {
"cookie1": "value1",
"cookie2": "value2"
},
"https://anotherdomain.com/": {
"cookieA": "valueA",
"cookieB": "valueB"
}
}
*/
get cookies() {
return this.jar.fetchAllCookies();
}
/**
* Sets a cookie
*
* @returns void.
*
* @example
setCookie
*/
setCookie(cookie, url, opts) {
const cookieObj = new tough_cookie_1.Cookie();
cookieObj.key = cookie.name;
cookieObj.value = cookie.value;
if (cookie.expires)
cookieObj.expires = cookie.expires;
if (cookie.sameSite)
cookieObj.sameSite = cookie.sameSite;
if (cookie.secure)
cookieObj.secure = cookie.secure;
if (cookie.domain)
cookieObj.domain = cookie.domain;
if (cookie.path)
cookieObj.path = cookie.path;
if (cookie.httpOnly)
cookieObj.httpOnly = cookie.httpOnly;
this.jar.setCookieSync(cookieObj, url, {});
}
/**
* The 'close' method closes the current session.
*
* @returns The response from the 'destroySession' function.
*/
async close() {
const payload = JSON.stringify({
sessionId: this.sessionId,
});
const response = await this.pool?.exec("destroySession", [payload]);
await this.pool?.terminate();
return response;
}
/**
* The 'freeMemory' method frees the memory used by the session with the provided id.
*
* @param id - The id of the session to free the memory of.
*
* @returns The response from the 'destroySession' function.
*/
async free(id) {
await this.pool?.exec("freeMemory", [id]);
return;
}
/**
* 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, {
headers: options?.headers,
redirect: options?.redirect,
additionalDecode: options?.additionalDecode || false,
proxy: options?.proxy,
cookies: options?.cookies,
byteResponse: options?.byteResponse || false,
hostOverride: options?.hostOverride || null,
...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, {
headers: options?.headers,
redirect: options?.redirect,
additionalDecode: options?.additionalDecode || false,
proxy: options?.proxy,
cookies: options?.cookies,
byteResponse: options?.byteResponse || false,
hostOverride: options?.hostOverride || null,
...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, {
headers: options?.headers,
redirect: options?.redirect,
additionalDecode: options?.additionalDecode || false,
proxy: options?.proxy,
cookies: options?.cookies,
hostOverride: options?.hostOverride || null,
...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, {
headers: options?.headers,
redirect: options?.redirect,
additionalDecode: options?.additionalDecode || false,
proxy: options?.proxy,
cookies: options?.cookies,
hostOverride: options?.hostOverride || null,
...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, {
body: options?.body,
headers: options?.headers,
redirect: options?.redirect,
additionalDecode: options?.additionalDecode || false,
proxy: options?.proxy,
cookies: options?.cookies,
byteResponse: options?.byteResponse || false,
hostOverride: options?.hostOverride || null,
...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, {
body: options?.body,
headers: options?.headers,
redirect: options?.redirect,
additionalDecode: options?.additionalDecode || false,
proxy: options?.proxy,
cookies: options?.cookies,
byteResponse: options?.byteResponse || false,
hostOverride: options?.hostOverride || null,
...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, {
body: options?.body,
headers: options?.headers,
redirect: options?.redirect,
additionalDecode: options?.additionalDecode || false,
proxy: options?.proxy,
cookies: options?.cookies,
byteResponse: options?.byteResponse || false,
hostOverride: options?.hostOverride || null,
...options,
});
}
/**
* The 'execute' method performs a HTTP request of the provided method to the provided URL with the provided options.
*
* @param method - The HTTP method of the request.
* @param url - The URL to perform the request to.
* @param options - The options for the request.
*
* @returns A new Response object.
*/
async execute(method, url, options) {
let headers = options?.headers ? options?.headers : this.headers;
let requestCookies = [];
if (options?.cookies) {
requestCookies = this.jar.mergeCookies(options.cookies, url);
}
let skeletonPayload = {
sessionId: this.sessionId,
followRedirects: options?.redirect || false,
forceHttp1: this.forceHttp1,
withDebug: this.debug,
headers,
headerOrder: this.headerOrder,
insecureSkipVerify: this.insecureSkipVerify,
additionalDecode: options?.additionalDecode,
proxyUrl: options?.proxy || this.proxy,
requestUrl: url,
requestMethod: method,
requestBody: options?.body || null,
requestCookies: requestCookies,
timeoutMilliseconds: this.timeout || null,
withRandomTLSExtensionOrder: this.randomTlsExtensionOrder,
isByteResponse: options?.byteResponse,
isByteRequest: (0, utils_1.isByteRequest)(headers),
requestHostOverride: options?.hostOverride,
disableIPV6: this.disableIPV6,
disableIPV4: this.disableIPV4,
isRotatingProxy: options?.isRotatingProxy ?? this.isRotatingProxy,
};
if (this.clientIdentifier) {
skeletonPayload["tlsClientIdentifier"] = this.clientIdentifier;
}
else if (this.ja3string) {
skeletonPayload["customTlsClient"] = {
ja3String: this.ja3string,
h2Settings: this.h2Settings,
h2SettingsOrder: this.h2SettingsOrder,
pseudoHeaderOrder: this.pseudoHeaderOrder,
connectionFlow: this.connectionFlow,
priorityFrames: this.priorityFrames,
headerPriority: this.headerPriority,
certCompressionAlgo: this.certCompressionAlgo,
supportedVersions: this.supportedVersions,
supportedSignatureAlgorithms: this.supportedSignatureAlgorithms,
keyShareCurves: this.keyShareCurves,
alpnProtocols: this.alpnProtocols,
alpsProtocols: this.alpsProtocols,
};
}
else
skeletonPayload["tlsClientIdentifier"] = session_1.ClientIdentifier.chrome_131;
const requestPayloadString = JSON.stringify(skeletonPayload);
let res = await this.pool?.exec("request", [
requestPayloadString,
]);
let cookies = this.jar.syncCookies(res?.cookies, url);
await this.free(res.id);
return new _1.Response({ ...res, cookies });
}
}
exports.Session = Session;
__decorate([
(0, decorators_1.verifyClientState)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], Session.prototype, "close", null);
__decorate([
(0, decorators_1.verifyClientState)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Promise)
], Session.prototype, "free", null);
__decorate([
(0, decorators_1.verifyClientState)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object]),
__metadata("design:returntype", void 0)
], Session.prototype, "get", null);
__decorate([
(0, decorators_1.verifyClientState)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object]),
__metadata("design:returntype", void 0)
], Session.prototype, "delete", null);
__decorate([
(0, decorators_1.verifyClientState)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object]),
__metadata("design:returntype", void 0)
], Session.prototype, "options", null);
__decorate([
(0, decorators_1.verifyClientState)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object]),
__metadata("design:returntype", void 0)
], Session.prototype, "head", null);
__decorate([
(0, decorators_1.verifyClientState)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object]),
__metadata("design:returntype", void 0)
], Session.prototype, "post", null);
__decorate([
(0, decorators_1.verifyClientState)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object]),
__metadata("design:returntype", void 0)
], Session.prototype, "patch", null);
__decorate([
(0, decorators_1.verifyClientState)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object]),
__metadata("design:returntype", void 0)
], Session.prototype, "put", null);