advanced-tls-client 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1143 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AdvancedTLSClient = void 0;
37
+ const tls = __importStar(require("tls"));
38
+ const net = __importStar(require("net"));
39
+ const http2 = __importStar(require("http2"));
40
+ const crypto = __importStar(require("crypto"));
41
+ const events_1 = require("events");
42
+ const zlib = __importStar(require("zlib"));
43
+ const util_1 = require("util");
44
+ const gunzip = (0, util_1.promisify)(zlib.gunzip);
45
+ const brotliDecompress = (0, util_1.promisify)(zlib.brotliDecompress);
46
+ const GREASE_VALUES = [0x0a0a, 0x1a1a, 0x2a2a, 0x3a3a, 0x4a4a, 0x5a5a, 0x6a6a, 0x7a7a, 0x8a8a, 0x9a9a, 0xaaaa, 0xbaba, 0xcaca, 0xdada, 0xeaea, 0xfafa];
47
+ class ProfileRegistry {
48
+ static getGrease() {
49
+ return GREASE_VALUES[Math.floor(Math.random() * GREASE_VALUES.length)];
50
+ }
51
+ static chromeMobile143Android() {
52
+ const grease1 = this.getGrease();
53
+ const grease2 = this.getGrease();
54
+ const grease3 = this.getGrease();
55
+ const grease4 = this.getGrease();
56
+ return {
57
+ name: 'chrome_mobile_143_android',
58
+ version: '143.0.0.0',
59
+ tls: {
60
+ cipherSuites: [
61
+ `GREASE_${grease1.toString(16)}`,
62
+ 'TLS_AES_128_GCM_SHA256',
63
+ 'TLS_AES_256_GCM_SHA384',
64
+ 'TLS_CHACHA20_POLY1305_SHA256',
65
+ 'ECDHE-ECDSA-AES128-GCM-SHA256',
66
+ 'ECDHE-RSA-AES128-GCM-SHA256',
67
+ 'ECDHE-ECDSA-AES256-GCM-SHA384',
68
+ 'ECDHE-RSA-AES256-GCM-SHA384',
69
+ 'ECDHE-ECDSA-CHACHA20-POLY1305',
70
+ 'ECDHE-RSA-CHACHA20-POLY1305',
71
+ 'ECDHE-RSA-AES128-SHA',
72
+ 'ECDHE-RSA-AES256-SHA',
73
+ 'AES128-GCM-SHA256',
74
+ 'AES256-GCM-SHA384',
75
+ 'AES128-SHA',
76
+ 'AES256-SHA'
77
+ ],
78
+ extensions: [
79
+ grease2,
80
+ 0xfe0d,
81
+ 0x001b,
82
+ 0x002b,
83
+ 0x0010,
84
+ 0x0023,
85
+ 0x002d,
86
+ 0x000b,
87
+ 0xff01,
88
+ 0x0005,
89
+ 0x000a,
90
+ 0x0017,
91
+ 0x0000,
92
+ 0x44cd,
93
+ 0x0033,
94
+ 0x0012,
95
+ 0x000d,
96
+ grease3
97
+ ],
98
+ supportedGroups: [
99
+ `GREASE_${grease4.toString(16)}`,
100
+ 'X25519Kyber768',
101
+ 'X25519',
102
+ 'prime256v1',
103
+ 'secp384r1'
104
+ ],
105
+ signatureAlgorithms: [
106
+ 'ecdsa_secp256r1_sha256',
107
+ 'rsa_pss_rsae_sha256',
108
+ 'rsa_pkcs1_sha256',
109
+ 'ecdsa_secp384r1_sha384',
110
+ 'rsa_pss_rsae_sha384',
111
+ 'rsa_pkcs1_sha384',
112
+ 'rsa_pss_rsae_sha512',
113
+ 'rsa_pkcs1_sha512'
114
+ ],
115
+ supportedVersions: [
116
+ `GREASE_${grease2.toString(16)}`,
117
+ 'TLSv1.3',
118
+ 'TLSv1.2'
119
+ ],
120
+ ecPointFormats: [0x00],
121
+ alpnProtocols: ['h2', 'http/1.1'],
122
+ pskKeyExchangeModes: [0x01],
123
+ compressionMethods: [0x00],
124
+ grease: true,
125
+ recordSizeLimit: 16385,
126
+ certificateCompression: [0x02],
127
+ ocspStapling: true,
128
+ signedCertificateTimestamp: true
129
+ },
130
+ http2: {
131
+ windowUpdate: 15663105,
132
+ headerTableSize: 65536,
133
+ enablePush: 0,
134
+ initialWindowSize: 6291456,
135
+ maxHeaderListSize: 262144,
136
+ maxFrameSize: 16384,
137
+ settingsOrder: [1, 2, 4, 6],
138
+ connectionPreface: Buffer.from('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'),
139
+ priorityFrames: [
140
+ {
141
+ streamId: 0,
142
+ weight: 256,
143
+ dependency: 0,
144
+ exclusive: true
145
+ }
146
+ ],
147
+ pseudoHeaderOrder: [':method', ':authority', ':scheme', ':path'],
148
+ headerOrder: [
149
+ 'sec-ch-ua',
150
+ 'sec-ch-ua-mobile',
151
+ 'sec-ch-ua-platform',
152
+ 'upgrade-insecure-requests',
153
+ 'user-agent',
154
+ 'accept',
155
+ 'sec-fetch-site',
156
+ 'sec-fetch-mode',
157
+ 'sec-fetch-dest',
158
+ 'accept-encoding',
159
+ 'accept-language',
160
+ 'priority'
161
+ ]
162
+ },
163
+ userAgent: 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Mobile Safari/537.36',
164
+ secChUa: '"Google Chrome";v="143", "Chromium";v="143", "Not A(Brand";v="24"',
165
+ secChUaPlatform: '"Android"',
166
+ secChUaMobile: '?1',
167
+ secFetchSite: 'none',
168
+ secFetchMode: 'navigate',
169
+ secFetchDest: 'document',
170
+ upgradeInsecureRequests: '1',
171
+ acceptLanguage: 'id,en-US;q=0.9,en;q=0.8,ms;q=0.7,ja;q=0.6,zh-CN;q=0.5,zh;q=0.4',
172
+ priority: 'u=0, i'
173
+ };
174
+ }
175
+ static chrome133PSK() {
176
+ const grease1 = this.getGrease();
177
+ const grease2 = this.getGrease();
178
+ const grease3 = this.getGrease();
179
+ const grease4 = this.getGrease();
180
+ return {
181
+ name: 'chrome_133_psk',
182
+ version: '133.0.0.0',
183
+ tls: {
184
+ cipherSuites: [
185
+ `GREASE_${grease1.toString(16)}`,
186
+ 'TLS_AES_128_GCM_SHA256',
187
+ 'TLS_AES_256_GCM_SHA384',
188
+ 'TLS_CHACHA20_POLY1305_SHA256',
189
+ 'ECDHE-ECDSA-AES128-GCM-SHA256',
190
+ 'ECDHE-RSA-AES128-GCM-SHA256',
191
+ 'ECDHE-ECDSA-AES256-GCM-SHA384',
192
+ 'ECDHE-RSA-AES256-GCM-SHA384',
193
+ 'ECDHE-ECDSA-CHACHA20-POLY1305',
194
+ 'ECDHE-RSA-CHACHA20-POLY1305',
195
+ 'ECDHE-RSA-AES128-SHA',
196
+ 'ECDHE-RSA-AES256-SHA',
197
+ 'AES128-GCM-SHA256',
198
+ 'AES256-GCM-SHA384',
199
+ 'AES128-SHA',
200
+ 'AES256-SHA'
201
+ ],
202
+ extensions: [
203
+ grease2,
204
+ 0x0000,
205
+ 0x0017,
206
+ 0xff01,
207
+ 0x000a,
208
+ 0x000b,
209
+ 0x0023,
210
+ 0x0010,
211
+ 0x0005,
212
+ 0x000d,
213
+ 0x0012,
214
+ 0x0033,
215
+ 0x002d,
216
+ 0x002b,
217
+ 0x001b,
218
+ 0x0015,
219
+ grease3
220
+ ],
221
+ supportedGroups: [
222
+ `GREASE_${grease4.toString(16)}`,
223
+ 'X25519Kyber768',
224
+ 'X25519',
225
+ 'prime256v1',
226
+ 'secp384r1'
227
+ ],
228
+ signatureAlgorithms: [
229
+ 'ecdsa_secp256r1_sha256',
230
+ 'rsa_pss_rsae_sha256',
231
+ 'rsa_pkcs1_sha256',
232
+ 'ecdsa_secp384r1_sha384',
233
+ 'rsa_pss_rsae_sha384',
234
+ 'rsa_pkcs1_sha384',
235
+ 'rsa_pss_rsae_sha512',
236
+ 'rsa_pkcs1_sha512'
237
+ ],
238
+ supportedVersions: [
239
+ `GREASE_${grease2.toString(16)}`,
240
+ 'TLSv1.3',
241
+ 'TLSv1.2'
242
+ ],
243
+ ecPointFormats: [0x00],
244
+ alpnProtocols: ['h2', 'http/1.1'],
245
+ pskKeyExchangeModes: [0x01],
246
+ compressionMethods: [0x00],
247
+ grease: true,
248
+ recordSizeLimit: 16385
249
+ },
250
+ http2: {
251
+ windowUpdate: 15663105,
252
+ headerTableSize: 65536,
253
+ enablePush: 0,
254
+ initialWindowSize: 6291456,
255
+ maxFrameSize: 16384,
256
+ maxHeaderListSize: 262144,
257
+ settingsOrder: [1, 2, 4, 6],
258
+ connectionPreface: Buffer.from('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'),
259
+ priorityFrames: [
260
+ {
261
+ streamId: 0,
262
+ weight: 256,
263
+ dependency: 0,
264
+ exclusive: true
265
+ }
266
+ ],
267
+ pseudoHeaderOrder: [':method', ':authority', ':scheme', ':path'],
268
+ headerOrder: [
269
+ 'cache-control',
270
+ 'sec-ch-ua',
271
+ 'sec-ch-ua-mobile',
272
+ 'sec-ch-ua-platform',
273
+ 'upgrade-insecure-requests',
274
+ 'user-agent',
275
+ 'accept',
276
+ 'sec-fetch-site',
277
+ 'sec-fetch-mode',
278
+ 'sec-fetch-user',
279
+ 'sec-fetch-dest',
280
+ 'accept-encoding',
281
+ 'accept-language'
282
+ ]
283
+ },
284
+ userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
285
+ secChUa: '"Google Chrome";v="133", "Chromium";v="133", "Not_A Brand";v="24"',
286
+ secChUaPlatform: '"Windows"',
287
+ secChUaMobile: '?0',
288
+ secFetchSite: 'none',
289
+ secFetchMode: 'navigate',
290
+ secFetchDest: 'document'
291
+ };
292
+ }
293
+ static chrome133() {
294
+ const grease1 = this.getGrease();
295
+ const grease2 = this.getGrease();
296
+ const grease3 = this.getGrease();
297
+ const grease4 = this.getGrease();
298
+ return {
299
+ name: 'chrome_133',
300
+ version: '133.0.0.0',
301
+ tls: {
302
+ cipherSuites: [
303
+ `GREASE_${grease1.toString(16)}`,
304
+ 'TLS_AES_128_GCM_SHA256',
305
+ 'TLS_AES_256_GCM_SHA384',
306
+ 'TLS_CHACHA20_POLY1305_SHA256',
307
+ 'ECDHE-ECDSA-AES128-GCM-SHA256',
308
+ 'ECDHE-RSA-AES128-GCM-SHA256',
309
+ 'ECDHE-ECDSA-AES256-GCM-SHA384',
310
+ 'ECDHE-RSA-AES256-GCM-SHA384',
311
+ 'ECDHE-ECDSA-CHACHA20-POLY1305',
312
+ 'ECDHE-RSA-CHACHA20-POLY1305',
313
+ 'ECDHE-RSA-AES128-SHA',
314
+ 'ECDHE-RSA-AES256-SHA',
315
+ 'AES128-GCM-SHA256',
316
+ 'AES256-GCM-SHA384',
317
+ 'AES128-SHA',
318
+ 'AES256-SHA'
319
+ ],
320
+ extensions: [
321
+ grease2,
322
+ 0x0000,
323
+ 0x0017,
324
+ 0xff01,
325
+ 0x000a,
326
+ 0x000b,
327
+ 0x0023,
328
+ 0x0010,
329
+ 0x0005,
330
+ 0x000d,
331
+ 0x0012,
332
+ 0x0033,
333
+ 0x002d,
334
+ 0x002b,
335
+ 0x001b,
336
+ 0x0015,
337
+ grease3
338
+ ],
339
+ supportedGroups: [
340
+ `GREASE_${grease4.toString(16)}`,
341
+ 'X25519Kyber768',
342
+ 'X25519',
343
+ 'prime256v1',
344
+ 'secp384r1'
345
+ ],
346
+ signatureAlgorithms: [
347
+ 'ecdsa_secp256r1_sha256',
348
+ 'rsa_pss_rsae_sha256',
349
+ 'rsa_pkcs1_sha256',
350
+ 'ecdsa_secp384r1_sha384',
351
+ 'rsa_pss_rsae_sha384',
352
+ 'rsa_pkcs1_sha384',
353
+ 'rsa_pss_rsae_sha512',
354
+ 'rsa_pkcs1_sha512'
355
+ ],
356
+ supportedVersions: [
357
+ `GREASE_${grease2.toString(16)}`,
358
+ 'TLSv1.3',
359
+ 'TLSv1.2'
360
+ ],
361
+ ecPointFormats: [0x00],
362
+ alpnProtocols: ['h2', 'http/1.1'],
363
+ pskKeyExchangeModes: [0x01],
364
+ compressionMethods: [0x00],
365
+ grease: true,
366
+ recordSizeLimit: 16385
367
+ },
368
+ http2: {
369
+ windowUpdate: 15663105,
370
+ headerTableSize: 65536,
371
+ enablePush: 0,
372
+ initialWindowSize: 6291456,
373
+ maxFrameSize: 16384,
374
+ maxHeaderListSize: 262144,
375
+ settingsOrder: [1, 2, 4, 6],
376
+ connectionPreface: Buffer.from('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'),
377
+ priorityFrames: [
378
+ {
379
+ streamId: 0,
380
+ weight: 256,
381
+ dependency: 0,
382
+ exclusive: true
383
+ }
384
+ ],
385
+ pseudoHeaderOrder: [':method', ':authority', ':scheme', ':path'],
386
+ headerOrder: [
387
+ 'cache-control',
388
+ 'sec-ch-ua',
389
+ 'sec-ch-ua-mobile',
390
+ 'sec-ch-ua-platform',
391
+ 'upgrade-insecure-requests',
392
+ 'user-agent',
393
+ 'accept',
394
+ 'sec-fetch-site',
395
+ 'sec-fetch-mode',
396
+ 'sec-fetch-user',
397
+ 'sec-fetch-dest',
398
+ 'accept-encoding',
399
+ 'accept-language'
400
+ ]
401
+ },
402
+ userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
403
+ secChUa: '"Google Chrome";v="133", "Chromium";v="133", "Not_A Brand";v="24"',
404
+ secChUaPlatform: '"Windows"',
405
+ secChUaMobile: '?0',
406
+ secFetchSite: 'none',
407
+ secFetchMode: 'navigate',
408
+ secFetchDest: 'document'
409
+ };
410
+ }
411
+ static firefox117() {
412
+ return {
413
+ name: 'firefox_117',
414
+ version: '117.0',
415
+ tls: {
416
+ cipherSuites: [
417
+ 'TLS_AES_128_GCM_SHA256',
418
+ 'TLS_CHACHA20_POLY1305_SHA256',
419
+ 'TLS_AES_256_GCM_SHA384',
420
+ 'ECDHE-ECDSA-AES128-GCM-SHA256',
421
+ 'ECDHE-RSA-AES128-GCM-SHA256',
422
+ 'ECDHE-ECDSA-CHACHA20-POLY1305',
423
+ 'ECDHE-RSA-CHACHA20-POLY1305',
424
+ 'ECDHE-ECDSA-AES256-GCM-SHA384',
425
+ 'ECDHE-RSA-AES256-GCM-SHA384',
426
+ 'ECDHE-ECDSA-AES256-SHA',
427
+ 'ECDHE-ECDSA-AES128-SHA',
428
+ 'ECDHE-RSA-AES128-SHA',
429
+ 'ECDHE-RSA-AES256-SHA',
430
+ 'AES128-GCM-SHA256',
431
+ 'AES256-GCM-SHA384',
432
+ 'AES128-SHA',
433
+ 'AES256-SHA'
434
+ ],
435
+ extensions: [0x0000, 0x0017, 0xff01, 0x000a, 0x000b, 0x0023, 0x0010, 0x0005, 0x0022, 0x0033, 0x002b, 0x000d, 0x002d, 0x0029, 0x0015],
436
+ supportedGroups: ['X25519', 'prime256v1', 'secp384r1', 'secp521r1', 'ffdhe2048', 'ffdhe3072'],
437
+ signatureAlgorithms: [
438
+ 'ecdsa_secp256r1_sha256',
439
+ 'ecdsa_secp384r1_sha384',
440
+ 'ecdsa_secp521r1_sha512',
441
+ 'rsa_pss_rsae_sha256',
442
+ 'rsa_pss_rsae_sha384',
443
+ 'rsa_pss_rsae_sha512',
444
+ 'rsa_pkcs1_sha256',
445
+ 'rsa_pkcs1_sha384',
446
+ 'rsa_pkcs1_sha512',
447
+ 'ecdsa_sha1',
448
+ 'rsa_pkcs1_sha1'
449
+ ],
450
+ supportedVersions: ['TLSv1.3', 'TLSv1.2'],
451
+ ecPointFormats: [0x00],
452
+ alpnProtocols: ['h2', 'http/1.1'],
453
+ pskKeyExchangeModes: [0x01],
454
+ compressionMethods: [0x00],
455
+ grease: false
456
+ },
457
+ http2: {
458
+ windowUpdate: 12517377,
459
+ headerTableSize: 65536,
460
+ enablePush: 0,
461
+ initialWindowSize: 131072,
462
+ maxFrameSize: 16384,
463
+ settingsOrder: [1, 4, 5],
464
+ connectionPreface: Buffer.from('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'),
465
+ priorityFrames: [
466
+ { streamId: 3, weight: 200, dependency: 0, exclusive: false },
467
+ { streamId: 5, weight: 100, dependency: 0, exclusive: false },
468
+ { streamId: 7, weight: 0, dependency: 0, exclusive: false },
469
+ { streamId: 9, weight: 0, dependency: 7, exclusive: false },
470
+ { streamId: 11, weight: 0, dependency: 3, exclusive: false },
471
+ { streamId: 13, weight: 240, dependency: 0, exclusive: false }
472
+ ],
473
+ pseudoHeaderOrder: [':method', ':path', ':authority', ':scheme'],
474
+ headerPriority: { streamDep: 13, exclusive: false, weight: 41 }
475
+ },
476
+ userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:117.0) Gecko/20100101 Firefox/117.0',
477
+ secChUa: '',
478
+ secChUaPlatform: '',
479
+ secChUaMobile: '',
480
+ secFetchSite: 'none',
481
+ secFetchMode: 'navigate',
482
+ secFetchDest: 'document'
483
+ };
484
+ }
485
+ static safariIOS18() {
486
+ const grease1 = this.getGrease();
487
+ const grease2 = this.getGrease();
488
+ return {
489
+ name: 'safari_ios_18_0',
490
+ version: '18.0',
491
+ tls: {
492
+ cipherSuites: [
493
+ `GREASE_${grease1.toString(16)}`,
494
+ 'TLS_AES_128_GCM_SHA256',
495
+ 'TLS_AES_256_GCM_SHA384',
496
+ 'TLS_CHACHA20_POLY1305_SHA256',
497
+ 'ECDHE-ECDSA-AES256-GCM-SHA384',
498
+ 'ECDHE-ECDSA-AES128-GCM-SHA256',
499
+ 'ECDHE-ECDSA-CHACHA20-POLY1305',
500
+ 'ECDHE-RSA-AES256-GCM-SHA384',
501
+ 'ECDHE-RSA-AES128-GCM-SHA256',
502
+ 'ECDHE-RSA-CHACHA20-POLY1305',
503
+ 'ECDHE-ECDSA-AES256-SHA',
504
+ 'ECDHE-ECDSA-AES128-SHA',
505
+ 'ECDHE-RSA-AES256-SHA',
506
+ 'ECDHE-RSA-AES128-SHA',
507
+ 'AES256-GCM-SHA384',
508
+ 'AES128-GCM-SHA256',
509
+ 'AES256-SHA',
510
+ 'AES128-SHA',
511
+ 'ECDHE-ECDSA-DES-CBC3-SHA',
512
+ 'ECDHE-RSA-DES-CBC3-SHA',
513
+ 'DES-CBC3-SHA'
514
+ ],
515
+ extensions: [
516
+ grease2,
517
+ 0x0000,
518
+ 0x0017,
519
+ 0xff01,
520
+ 0x000a,
521
+ 0x000b,
522
+ 0x0010,
523
+ 0x0005,
524
+ 0x000d,
525
+ 0x0012,
526
+ 0x0033,
527
+ 0x002d,
528
+ 0x002b,
529
+ 0x0015
530
+ ],
531
+ supportedGroups: ['X25519', 'prime256v1', 'secp384r1', 'secp521r1'],
532
+ signatureAlgorithms: [
533
+ 'ecdsa_secp256r1_sha256',
534
+ 'rsa_pss_rsae_sha256',
535
+ 'rsa_pkcs1_sha256',
536
+ 'ecdsa_secp384r1_sha384',
537
+ 'ecdsa_sha1',
538
+ 'rsa_pss_rsae_sha384',
539
+ 'rsa_pss_rsae_sha384',
540
+ 'rsa_pkcs1_sha384',
541
+ 'rsa_pss_rsae_sha512',
542
+ 'rsa_pkcs1_sha512',
543
+ 'rsa_pkcs1_sha1'
544
+ ],
545
+ supportedVersions: ['TLSv1.3', 'TLSv1.2', 'TLSv1.1', 'TLSv1.0'],
546
+ ecPointFormats: [0x00],
547
+ alpnProtocols: ['h2', 'http/1.1'],
548
+ pskKeyExchangeModes: [0x01],
549
+ compressionMethods: [0x00],
550
+ grease: true
551
+ },
552
+ http2: {
553
+ windowUpdate: 10420225,
554
+ headerTableSize: 4096,
555
+ enablePush: 0,
556
+ maxConcurrentStreams: 100,
557
+ initialWindowSize: 2097152,
558
+ maxFrameSize: 16384,
559
+ settingsOrder: [2, 3, 4, 8, 9],
560
+ connectionPreface: Buffer.from('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'),
561
+ priorityFrames: [],
562
+ pseudoHeaderOrder: [':method', ':scheme', ':authority', ':path']
563
+ },
564
+ userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1',
565
+ secChUa: '',
566
+ secChUaPlatform: '',
567
+ secChUaMobile: '?1',
568
+ secFetchSite: 'none',
569
+ secFetchMode: 'navigate',
570
+ secFetchDest: 'document'
571
+ };
572
+ }
573
+ static get(name) {
574
+ switch (name.toLowerCase()) {
575
+ case 'chrome_mobile_143_android': return this.chromeMobile143Android();
576
+ case 'chrome_133_psk': return this.chrome133PSK();
577
+ case 'chrome_133': return this.chrome133();
578
+ case 'firefox_117': return this.firefox117();
579
+ case 'safari_ios_18_0': return this.safariIOS18();
580
+ default: return this.chrome133();
581
+ }
582
+ }
583
+ static get latest() {
584
+ return this.chrome133();
585
+ }
586
+ static get latestMobile() {
587
+ return this.chromeMobile143Android();
588
+ }
589
+ }
590
+ class CookieJar {
591
+ constructor() {
592
+ this.cookies = new Map();
593
+ }
594
+ setCookie(domain, name, value, options = {}) {
595
+ if (!this.cookies.has(domain))
596
+ this.cookies.set(domain, new Map());
597
+ this.cookies.get(domain).set(name, { value, expires: options.expires, path: options.path || '/', domain });
598
+ }
599
+ getCookies(domain, path = '/') {
600
+ const domainCookies = this.cookies.get(domain);
601
+ if (!domainCookies)
602
+ return '';
603
+ const validCookies = [];
604
+ const now = new Date();
605
+ for (const [name, cookie] of domainCookies) {
606
+ if (cookie.expires && cookie.expires < now) {
607
+ domainCookies.delete(name);
608
+ continue;
609
+ }
610
+ if (path.startsWith(cookie.path))
611
+ validCookies.push(`${name}=${cookie.value}`);
612
+ }
613
+ return validCookies.join('; ');
614
+ }
615
+ parseSetCookie(domain, setCookieHeaders) {
616
+ for (const header of setCookieHeaders) {
617
+ const parts = header.split(';').map(p => p.trim());
618
+ const [nameValue] = parts;
619
+ const [name, value] = nameValue.split('=');
620
+ const options = { path: '/' };
621
+ for (let i = 1; i < parts.length; i++) {
622
+ const [key, val] = parts[i].split('=');
623
+ if (key.toLowerCase() === 'expires')
624
+ options.expires = new Date(val);
625
+ else if (key.toLowerCase() === 'path')
626
+ options.path = val;
627
+ }
628
+ this.setCookie(domain, name, value, options);
629
+ }
630
+ }
631
+ }
632
+ class TLSSocketManager extends events_1.EventEmitter {
633
+ constructor(profile) {
634
+ super();
635
+ this.socket = null;
636
+ this.tlsSocket = null;
637
+ this.startTime = 0;
638
+ this.hostname = '';
639
+ this.profile = profile;
640
+ this.timing = { socket: 0, lookup: 0, connect: 0, secureConnect: 0, response: 0, end: 0, total: 0 };
641
+ }
642
+ convertCipherSuite(suite) {
643
+ const cipherMap = {
644
+ 'TLS_AES_128_GCM_SHA256': 'TLS_AES_128_GCM_SHA256',
645
+ 'TLS_AES_256_GCM_SHA384': 'TLS_AES_256_GCM_SHA384',
646
+ 'TLS_CHACHA20_POLY1305_SHA256': 'TLS_CHACHA20_POLY1305_SHA256',
647
+ 'ECDHE-ECDSA-AES128-GCM-SHA256': 'ECDHE-ECDSA-AES128-GCM-SHA256',
648
+ 'ECDHE-RSA-AES128-GCM-SHA256': 'ECDHE-RSA-AES128-GCM-SHA256',
649
+ 'ECDHE-ECDSA-AES256-GCM-SHA384': 'ECDHE-ECDSA-AES256-GCM-SHA384',
650
+ 'ECDHE-RSA-AES256-GCM-SHA384': 'ECDHE-RSA-AES256-GCM-SHA384',
651
+ 'ECDHE-ECDSA-CHACHA20-POLY1305': 'ECDHE-ECDSA-CHACHA20-POLY1305',
652
+ 'ECDHE-RSA-CHACHA20-POLY1305': 'ECDHE-RSA-CHACHA20-POLY1305',
653
+ 'ECDHE-RSA-AES128-SHA': 'ECDHE-RSA-AES128-SHA',
654
+ 'ECDHE-RSA-AES256-SHA': 'ECDHE-RSA-AES256-SHA',
655
+ 'AES128-GCM-SHA256': 'AES128-GCM-SHA256',
656
+ 'AES256-GCM-SHA384': 'AES256-GCM-SHA384',
657
+ 'AES128-SHA': 'AES128-SHA',
658
+ 'AES256-SHA': 'AES256-SHA'
659
+ };
660
+ if (suite.startsWith('GREASE_'))
661
+ return '';
662
+ return cipherMap[suite] || suite;
663
+ }
664
+ convertSupportedGroup(group) {
665
+ const groupMap = {
666
+ 'X25519Kyber768': 'X25519',
667
+ 'X25519': 'X25519',
668
+ 'prime256v1': 'prime256v1',
669
+ 'secp384r1': 'secp384r1'
670
+ };
671
+ if (group.startsWith('GREASE_'))
672
+ return '';
673
+ return groupMap[group] || group;
674
+ }
675
+ async connect(hostname, port) {
676
+ this.hostname = hostname;
677
+ this.startTime = Date.now();
678
+ return new Promise((resolve, reject) => {
679
+ const timeout = setTimeout(() => {
680
+ this.destroy();
681
+ reject(new Error('Connection timeout'));
682
+ }, 30000);
683
+ this.socket = new net.Socket();
684
+ this.socket.setKeepAlive(true, 60000);
685
+ this.socket.setNoDelay(true);
686
+ this.timing.socket = Date.now() - this.startTime;
687
+ this.socket.on('lookup', () => {
688
+ this.timing.lookup = Date.now() - this.startTime;
689
+ });
690
+ this.socket.connect(port, hostname, () => {
691
+ this.timing.connect = Date.now() - this.startTime;
692
+ const ciphers = this.profile.tls.cipherSuites
693
+ .map(suite => this.convertCipherSuite(suite))
694
+ .filter(suite => suite !== '')
695
+ .join(':');
696
+ const curves = this.profile.tls.supportedGroups
697
+ .map(group => this.convertSupportedGroup(group))
698
+ .filter(group => group !== '')
699
+ .join(':');
700
+ const tlsOptions = {
701
+ socket: this.socket,
702
+ servername: hostname,
703
+ ALPNProtocols: this.profile.tls.alpnProtocols,
704
+ ciphers: ciphers,
705
+ minVersion: 'TLSv1.2',
706
+ maxVersion: 'TLSv1.3',
707
+ ecdhCurve: curves,
708
+ sigalgs: this.profile.tls.signatureAlgorithms.join(':'),
709
+ rejectUnauthorized: false,
710
+ requestCert: false,
711
+ honorCipherOrder: true,
712
+ sessionTimeout: 300
713
+ };
714
+ this.tlsSocket = tls.connect(tlsOptions);
715
+ this.tlsSocket.on('secureConnect', () => {
716
+ clearTimeout(timeout);
717
+ this.timing.secureConnect = Date.now() - this.startTime;
718
+ resolve(this.tlsSocket);
719
+ });
720
+ this.tlsSocket.on('error', (err) => {
721
+ clearTimeout(timeout);
722
+ this.destroy();
723
+ reject(err);
724
+ });
725
+ });
726
+ this.socket.on('error', (err) => {
727
+ clearTimeout(timeout);
728
+ this.destroy();
729
+ reject(err);
730
+ });
731
+ this.socket.on('timeout', () => {
732
+ clearTimeout(timeout);
733
+ this.destroy();
734
+ reject(new Error('Socket timeout'));
735
+ });
736
+ });
737
+ }
738
+ getTiming() {
739
+ return { ...this.timing, total: Date.now() - this.startTime };
740
+ }
741
+ destroy() {
742
+ if (this.tlsSocket && !this.tlsSocket.destroyed) {
743
+ this.tlsSocket.removeAllListeners();
744
+ this.tlsSocket.destroy();
745
+ this.tlsSocket = null;
746
+ }
747
+ if (this.socket && !this.socket.destroyed) {
748
+ this.socket.removeAllListeners();
749
+ this.socket.destroy();
750
+ this.socket = null;
751
+ }
752
+ }
753
+ isConnected() {
754
+ return this.tlsSocket !== null && !this.tlsSocket.destroyed;
755
+ }
756
+ getSocket() {
757
+ return this.tlsSocket;
758
+ }
759
+ getHostname() {
760
+ return this.hostname;
761
+ }
762
+ }
763
+ class HTTP2ClientManager {
764
+ constructor(tlsSocket, profile, hostname) {
765
+ this.client = null;
766
+ this.tlsSocket = tlsSocket;
767
+ this.profile = profile;
768
+ this.hostname = hostname;
769
+ }
770
+ async createSession() {
771
+ return new Promise((resolve, reject) => {
772
+ const settingsMap = {};
773
+ this.profile.http2.settingsOrder.forEach(settingId => {
774
+ switch (settingId) {
775
+ case 1:
776
+ settingsMap.headerTableSize = this.profile.http2.headerTableSize;
777
+ break;
778
+ case 2:
779
+ settingsMap.enablePush = this.profile.http2.enablePush === 1;
780
+ break;
781
+ case 3:
782
+ if (this.profile.http2.maxConcurrentStreams !== undefined) {
783
+ settingsMap.maxConcurrentStreams = this.profile.http2.maxConcurrentStreams;
784
+ }
785
+ break;
786
+ case 4:
787
+ settingsMap.initialWindowSize = this.profile.http2.initialWindowSize;
788
+ break;
789
+ case 5:
790
+ if (this.profile.http2.maxFrameSize !== undefined) {
791
+ settingsMap.maxFrameSize = this.profile.http2.maxFrameSize;
792
+ }
793
+ break;
794
+ case 6:
795
+ if (this.profile.http2.maxHeaderListSize !== undefined) {
796
+ settingsMap.maxHeaderListSize = this.profile.http2.maxHeaderListSize;
797
+ }
798
+ break;
799
+ }
800
+ });
801
+ const settings = {
802
+ createConnection: () => this.tlsSocket,
803
+ settings: settingsMap
804
+ };
805
+ this.client = http2.connect(`https://${this.hostname}`, settings);
806
+ this.client.on('connect', () => {
807
+ resolve(this.client);
808
+ });
809
+ this.client.on('error', reject);
810
+ });
811
+ }
812
+ request(path, headers) {
813
+ if (!this.client)
814
+ throw new Error('HTTP2 session not established');
815
+ const orderedHeaders = {};
816
+ this.profile.http2.pseudoHeaderOrder.forEach(pseudo => {
817
+ if (headers[pseudo]) {
818
+ orderedHeaders[pseudo] = headers[pseudo];
819
+ }
820
+ });
821
+ if (this.profile.http2.headerOrder) {
822
+ this.profile.http2.headerOrder.forEach(headerName => {
823
+ if (headers[headerName] && !headerName.startsWith(':')) {
824
+ orderedHeaders[headerName] = headers[headerName];
825
+ }
826
+ });
827
+ Object.keys(headers).forEach(key => {
828
+ if (!key.startsWith(':') && !orderedHeaders[key]) {
829
+ orderedHeaders[key] = headers[key];
830
+ }
831
+ });
832
+ }
833
+ else {
834
+ Object.assign(orderedHeaders, headers);
835
+ }
836
+ const requestOptions = { ...orderedHeaders };
837
+ if (this.profile.http2.priorityFrames && this.profile.http2.priorityFrames.length > 0) {
838
+ const priority = this.profile.http2.priorityFrames[0];
839
+ if (priority.weight)
840
+ requestOptions.weight = priority.weight;
841
+ if (priority.exclusive !== undefined)
842
+ requestOptions.exclusive = priority.exclusive;
843
+ if (priority.dependency !== undefined && priority.dependency !== 0)
844
+ requestOptions.parent = priority.dependency;
845
+ }
846
+ const stream = this.client.request(requestOptions);
847
+ if (this.profile.http2.headerPriority) {
848
+ try {
849
+ stream.priority({
850
+ parent: this.profile.http2.headerPriority.streamDep,
851
+ weight: this.profile.http2.headerPriority.weight,
852
+ exclusive: this.profile.http2.headerPriority.exclusive
853
+ });
854
+ }
855
+ catch (e) { }
856
+ }
857
+ return stream;
858
+ }
859
+ getClient() {
860
+ return this.client;
861
+ }
862
+ isConnected() {
863
+ return this.client !== null && !this.client.destroyed;
864
+ }
865
+ destroy() {
866
+ if (this.client && !this.client.destroyed) {
867
+ this.client.close();
868
+ this.client = null;
869
+ }
870
+ }
871
+ }
872
+ class AdvancedTLSClient {
873
+ constructor(profileName) {
874
+ this.sessionCache = new Map();
875
+ this.cookieJar = new CookieJar();
876
+ this.maxCachedSessions = 10;
877
+ this.sessionTimeout = 300000;
878
+ this.cleanupInterval = null;
879
+ this.profile = profileName ? ProfileRegistry.get(profileName) : ProfileRegistry.latest;
880
+ this.startSessionCleanup();
881
+ }
882
+ startSessionCleanup() {
883
+ this.cleanupInterval = setInterval(() => {
884
+ const now = Date.now();
885
+ for (const [key, session] of this.sessionCache) {
886
+ if (now - session.lastUsed > this.sessionTimeout) {
887
+ session.http2Manager.destroy();
888
+ session.tlsManager.destroy();
889
+ this.sessionCache.delete(key);
890
+ }
891
+ }
892
+ }, 60000);
893
+ if (this.cleanupInterval.unref) {
894
+ this.cleanupInterval.unref();
895
+ }
896
+ }
897
+ async request(url, options = {}) {
898
+ const maxRedirects = options.maxRedirects ?? 5;
899
+ const followRedirects = options.followRedirects !== false;
900
+ let redirectCount = 0;
901
+ let currentUrl = url;
902
+ let response;
903
+ while (true) {
904
+ response = await this.performRequest(currentUrl, options);
905
+ if (followRedirects && [301, 302, 303, 307, 308].includes(response.statusCode)) {
906
+ if (redirectCount >= maxRedirects) {
907
+ throw new Error(`Too many redirects (max: ${maxRedirects})`);
908
+ }
909
+ const locationHeader = response.headers['location'];
910
+ if (!locationHeader)
911
+ break;
912
+ const location = Array.isArray(locationHeader) ? locationHeader[0] : locationHeader;
913
+ currentUrl = new URL(location, currentUrl).toString();
914
+ redirectCount++;
915
+ if ([301, 302, 303].includes(response.statusCode)) {
916
+ options.method = 'GET';
917
+ delete options.body;
918
+ }
919
+ }
920
+ else {
921
+ break;
922
+ }
923
+ }
924
+ return response;
925
+ }
926
+ async performRequest(url, options = {}) {
927
+ const parsedUrl = new URL(url);
928
+ const hostname = parsedUrl.hostname;
929
+ const port = parsedUrl.port ? parseInt(parsedUrl.port) : 443;
930
+ const path = parsedUrl.pathname + parsedUrl.search;
931
+ const cacheKey = `${hostname}:${port}`;
932
+ let session = this.sessionCache.get(cacheKey);
933
+ if (!session || !this.isSessionAlive(session)) {
934
+ if (session) {
935
+ session.http2Manager.destroy();
936
+ session.tlsManager.destroy();
937
+ this.sessionCache.delete(cacheKey);
938
+ }
939
+ const tlsManager = new TLSSocketManager(this.profile);
940
+ const tlsSocket = await tlsManager.connect(hostname, port);
941
+ const http2Manager = new HTTP2ClientManager(tlsSocket, this.profile, hostname);
942
+ await http2Manager.createSession();
943
+ session = { tlsManager, http2Manager, lastUsed: Date.now() };
944
+ if (this.sessionCache.size >= this.maxCachedSessions) {
945
+ const oldestKey = Array.from(this.sessionCache.entries())
946
+ .sort((a, b) => a[1].lastUsed - b[1].lastUsed)[0][0];
947
+ const oldest = this.sessionCache.get(oldestKey);
948
+ oldest.http2Manager.destroy();
949
+ oldest.tlsManager.destroy();
950
+ this.sessionCache.delete(oldestKey);
951
+ }
952
+ this.sessionCache.set(cacheKey, session);
953
+ }
954
+ session.lastUsed = Date.now();
955
+ const headers = this.buildHeaders(hostname, path, options);
956
+ const stream = session.http2Manager.request(path, headers);
957
+ return new Promise((resolve, reject) => {
958
+ const chunks = [];
959
+ let responseHeaders = {};
960
+ let statusCode = 0;
961
+ stream.on('response', (headers) => {
962
+ responseHeaders = headers;
963
+ statusCode = Number(headers[':status']);
964
+ const setCookieHeaders = headers['set-cookie'];
965
+ if (setCookieHeaders) {
966
+ const cookieArray = Array.isArray(setCookieHeaders) ? setCookieHeaders : [setCookieHeaders];
967
+ this.cookieJar.parseSetCookie(hostname, cookieArray);
968
+ }
969
+ });
970
+ stream.on('data', (chunk) => chunks.push(chunk));
971
+ stream.on('end', async () => {
972
+ stream.removeAllListeners();
973
+ let body = Buffer.concat(chunks);
974
+ const timing = session.tlsManager.getTiming();
975
+ timing.end = Date.now();
976
+ timing.total = timing.end - (Date.now() - timing.end);
977
+ if (options.decompress !== false) {
978
+ const encoding = responseHeaders['content-encoding'];
979
+ if (encoding === 'gzip')
980
+ body = await gunzip(body);
981
+ else if (encoding === 'br')
982
+ body = await brotliDecompress(body);
983
+ }
984
+ let text;
985
+ let json;
986
+ try {
987
+ text = body.toString('utf-8');
988
+ if ((responseHeaders['content-type'] || '').includes('application/json')) {
989
+ json = JSON.parse(text);
990
+ }
991
+ }
992
+ catch (e) { }
993
+ const ja3 = this.generateJA3();
994
+ resolve({
995
+ statusCode,
996
+ headers: responseHeaders,
997
+ body,
998
+ text,
999
+ json,
1000
+ timing,
1001
+ fingerprints: {
1002
+ ja3,
1003
+ ja3Hash: crypto.createHash('md5').update(ja3).digest('hex'),
1004
+ akamai: `1:${this.profile.http2.headerTableSize};2:${this.profile.http2.enablePush};4:${this.profile.http2.initialWindowSize};6:${this.profile.http2.maxHeaderListSize ?? ''}|00|0|m,a,s,p`
1005
+ }
1006
+ });
1007
+ });
1008
+ stream.on('error', (err) => {
1009
+ stream.removeAllListeners();
1010
+ reject(err);
1011
+ });
1012
+ if (options.body) {
1013
+ const bodyBuffer = Buffer.isBuffer(options.body) ? options.body : Buffer.from(options.body);
1014
+ stream.write(bodyBuffer);
1015
+ }
1016
+ stream.end();
1017
+ });
1018
+ }
1019
+ generateJA3() {
1020
+ const version = '771';
1021
+ const ciphers = this.profile.tls.cipherSuites
1022
+ .filter(c => !c.startsWith('GREASE_'))
1023
+ .map(c => {
1024
+ const map = {
1025
+ 'TLS_AES_128_GCM_SHA256': '4865',
1026
+ 'TLS_AES_256_GCM_SHA384': '4866',
1027
+ 'TLS_CHACHA20_POLY1305_SHA256': '4867',
1028
+ 'ECDHE-ECDSA-AES128-GCM-SHA256': '49195',
1029
+ 'ECDHE-RSA-AES128-GCM-SHA256': '49199',
1030
+ 'ECDHE-ECDSA-AES256-GCM-SHA384': '49196',
1031
+ 'ECDHE-RSA-AES256-GCM-SHA384': '49200',
1032
+ 'ECDHE-ECDSA-CHACHA20-POLY1305': '52393',
1033
+ 'ECDHE-RSA-CHACHA20-POLY1305': '52392',
1034
+ 'ECDHE-RSA-AES128-SHA': '49171',
1035
+ 'ECDHE-RSA-AES256-SHA': '49172',
1036
+ 'AES128-GCM-SHA256': '156',
1037
+ 'AES256-GCM-SHA384': '157',
1038
+ 'AES128-SHA': '47',
1039
+ 'AES256-SHA': '53'
1040
+ };
1041
+ return map[c] || '0';
1042
+ }).join('-');
1043
+ const extensions = this.profile.tls.extensions
1044
+ .filter(e => typeof e === 'number')
1045
+ .join('-');
1046
+ const groups = this.profile.tls.supportedGroups
1047
+ .filter(g => !g.startsWith('GREASE_'))
1048
+ .map(g => {
1049
+ const map = {
1050
+ 'X25519': '29',
1051
+ 'prime256v1': '23',
1052
+ 'secp384r1': '24',
1053
+ 'secp521r1': '25',
1054
+ 'X25519Kyber768': '25497'
1055
+ };
1056
+ return map[g] || '0';
1057
+ }).join('-');
1058
+ const ecFormats = this.profile.tls.ecPointFormats.join('-');
1059
+ return `${version},${ciphers},${extensions},${groups},${ecFormats}`;
1060
+ }
1061
+ buildHeaders(hostname, path, options) {
1062
+ const method = (options.method || 'GET').toUpperCase();
1063
+ const headers = {
1064
+ ':method': method,
1065
+ ':authority': hostname,
1066
+ ':scheme': 'https',
1067
+ ':path': path
1068
+ };
1069
+ const defaultHeaders = {
1070
+ 'sec-ch-ua': this.profile.secChUa,
1071
+ 'sec-ch-ua-mobile': this.profile.secChUaMobile,
1072
+ 'sec-ch-ua-platform': this.profile.secChUaPlatform,
1073
+ 'upgrade-insecure-requests': this.profile.upgradeInsecureRequests || '1',
1074
+ 'user-agent': this.profile.userAgent,
1075
+ 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
1076
+ 'sec-fetch-site': this.profile.secFetchSite,
1077
+ 'sec-fetch-mode': this.profile.secFetchMode,
1078
+ 'sec-fetch-dest': this.profile.secFetchDest,
1079
+ 'accept-encoding': 'gzip, deflate, br, zstd',
1080
+ 'accept-language': this.profile.acceptLanguage || 'en-US,en;q=0.9'
1081
+ };
1082
+ if (this.profile.priority) {
1083
+ defaultHeaders['priority'] = this.profile.priority;
1084
+ }
1085
+ if (this.profile.http2.headerOrder) {
1086
+ this.profile.http2.headerOrder.forEach(headerName => {
1087
+ if (defaultHeaders[headerName]) {
1088
+ headers[headerName] = defaultHeaders[headerName];
1089
+ }
1090
+ });
1091
+ }
1092
+ Object.keys(defaultHeaders).forEach(key => {
1093
+ if (!headers[key]) {
1094
+ headers[key] = defaultHeaders[key];
1095
+ }
1096
+ });
1097
+ const cookies = options.cookies
1098
+ ? Object.entries(options.cookies).map(([k, v]) => `${k}=${v}`).join('; ')
1099
+ : this.cookieJar.getCookies(hostname, path);
1100
+ if (cookies)
1101
+ headers['cookie'] = cookies;
1102
+ if (options.headers)
1103
+ Object.assign(headers, options.headers);
1104
+ if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
1105
+ if (!headers['content-type'])
1106
+ headers['content-type'] = 'application/x-www-form-urlencoded';
1107
+ if (options.body) {
1108
+ const bodyLength = Buffer.isBuffer(options.body) ? options.body.length : Buffer.byteLength(options.body);
1109
+ headers['content-length'] = bodyLength.toString();
1110
+ }
1111
+ }
1112
+ return headers;
1113
+ }
1114
+ isSessionAlive(session) {
1115
+ try {
1116
+ return session.http2Manager.isConnected();
1117
+ }
1118
+ catch {
1119
+ return false;
1120
+ }
1121
+ }
1122
+ getCookies(domain) {
1123
+ return this.cookieJar.getCookies(domain);
1124
+ }
1125
+ setCookie(domain, name, value, options) {
1126
+ this.cookieJar.setCookie(domain, name, value, options);
1127
+ }
1128
+ destroy() {
1129
+ if (this.cleanupInterval) {
1130
+ clearInterval(this.cleanupInterval);
1131
+ this.cleanupInterval = null;
1132
+ }
1133
+ this.sessionCache.forEach(session => {
1134
+ try {
1135
+ session.http2Manager.destroy();
1136
+ session.tlsManager.destroy();
1137
+ }
1138
+ catch (e) { }
1139
+ });
1140
+ this.sessionCache.clear();
1141
+ }
1142
+ }
1143
+ exports.AdvancedTLSClient = AdvancedTLSClient;