@e-mc/request 0.3.2 → 0.4.0

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.
Files changed (4) hide show
  1. package/http/host/index.js +333 -333
  2. package/index.js +2186 -2186
  3. package/package.json +3 -3
  4. package/util.js +148 -148
package/index.js CHANGED
@@ -1,2189 +1,2189 @@
1
- "use strict";
2
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- const path = require("path");
5
- const fs = require("fs");
6
- const child_process = require("child_process");
7
- const http = require("http");
8
- const https = require("https");
9
- const http2 = require("http2");
10
- const dns = require("dns");
11
- const net = require("net");
12
- const stream = require("stream");
13
- const zlib = require("zlib");
14
- const qs = require("querystring");
15
- const combined = require("combined-stream");
16
- const yaml = require("js-yaml");
17
- const which = require("which");
18
- const lib_v4_1 = require("../module/lib-v4");
19
- const types_1 = require("../types");
20
- const module_1 = require("../module");
21
- const host_1 = require("./http/host");
22
- const util_1 = require("./util");
23
- const kSession = Symbol('session');
24
- const kHttpVersion = Symbol('httpVersion');
25
- const kIpVersion = Symbol('ipVersion');
26
- const kAgentTimeout = Symbol('agentTimeout');
27
- const kHeaders = Symbol('headers');
28
- const kCerts = Symbol('certs');
29
- const kDownloading = Symbol('downloading');
30
- const kSingleton = Symbol('singleton');
31
- const kHostInfo = Symbol('hostInfo');
32
- const kConnectDns = Symbol('connectDns');
33
- const kPendingDns = Symbol('pendingDns');
34
- const kConnectHttp = Symbol('connectHttp');
35
- const PLATFORM_WIN32 = process.platform === 'win32';
36
- const SUPPORT_ABORTSIGNAL = module_1.default.supported(15, 4);
37
- const HTTP = {
38
- HOST: {},
39
- HEADERS: {},
40
- VERSION: 1,
41
- PROXY: null
42
- };
43
- const TLS = {
44
- TEXT: {},
45
- FILE: {}
46
- };
47
- const DNS = {
48
- CACHE: Object.create(null),
49
- TIMEOUT: [],
50
- EXPIRES: 0,
51
- FAMILY: 0
52
- };
53
- const ARIA2 = {
54
- BIN: which.sync(PLATFORM_WIN32 ? 'aria2c.exe' : 'aria2c', { nothrow: true }) || '',
55
- PID_TIMER: null,
56
- PID_QUEUE: [],
57
- UPDATE_STATUS: 0,
58
- UPDATE_BROADCAST_ONLY: false,
59
- BT_STOP_TIMEOUT: 60,
60
- BT_TRACKER_CONNECT_TIMEOUT: 30,
61
- BT_TRACKER_TIMEOUT: 60,
62
- MAX_CONCURRENT_DOWNLOADS: 0,
63
- MAX_CONNECTION_PER_SERVER: 0,
64
- MIN_SPLIT_SIZE: '',
65
- DISK_CACHE: null,
66
- LOWEST_SPEED_LIMIT: null,
67
- ALWAYS_RESUME: false,
68
- FILE_ALLOCATION: 'none',
69
- CONF_PATH: ''
70
- };
71
- let KEEP_ALIVE = null;
72
- let ACCEPT_ENCODING = false;
73
- let READ_TIMEOUT = 0;
74
- let AGENT_TIMEOUT = 0;
75
- let LOG_HTTP = false;
76
- let LOG_TIMEPROCESS = true;
77
- let LOG_TIMEFORMAT = 'readable';
78
- function getBaseHeaders(uri, headers) {
79
- uri = (0, util_1.trimPath)(uri);
80
- let result;
81
- for (const pathname in headers) {
82
- if (pathname === uri || uri.startsWith(pathname + '/')) {
83
- (result || (result = [])).push([pathname, headers[pathname]]);
84
- }
85
- }
86
- if (result) {
87
- if (result.length > 1) {
88
- result.sort((a, b) => b[0].length - a[0].length);
89
- }
90
- return result[0][1];
91
- }
92
- }
93
- function setDnsCache(hostname, value) {
94
- if (DNS.EXPIRES > 0 && !DNS.CACHE[hostname]) {
95
- DNS.CACHE[hostname] = value;
96
- if (DNS.EXPIRES !== Infinity) {
97
- const timeout = setTimeout(() => {
98
- const index = DNS.TIMEOUT.findIndex(item => item === timeout);
99
- if (index !== -1) {
100
- DNS.TIMEOUT.splice(index, 1);
101
- }
102
- DNS.CACHE[hostname] = undefined;
103
- }, DNS.EXPIRES);
104
- DNS.TIMEOUT.push(timeout);
105
- }
106
- }
107
- }
108
- function isConnectionTimeout(err) {
109
- switch (err instanceof Error && err.code) {
110
- case 'ETIMEDOUT':
111
- case 'ECONNRESET':
112
- return true;
113
- default:
114
- return false;
115
- }
116
- }
117
- function setOutgoingHeaders(output, headers) {
118
- for (const href in headers) {
119
- output[href] = (0, util_1.normalizeHeaders)(headers[href]);
120
- }
121
- }
122
- function getProxySettings(request, agentTimeout) {
123
- const proxy = request.proxy;
124
- if ((0, types_1.isObject)(proxy) && proxy.address && proxy.port) {
125
- const port = (0, util_1.asInt)(proxy.port);
126
- const address = (!module_1.default.isURL(proxy.address) ? port === 80 ? 'http://' : 'https://' : '') + proxy.address;
127
- try {
128
- let host = new URL(address + ':' + port), include, exclude;
129
- if ((0, types_1.isString)(proxy.username)) {
130
- host = new URL(host.protocol + '//' + (0, util_1.getBasicAuth)(proxy.username, proxy.password) + host.host);
131
- }
132
- if ((0, types_1.isArray)(proxy.include)) {
133
- include = proxy.include;
134
- }
135
- else if ((0, types_1.isArray)(proxy.exclude)) {
136
- exclude = proxy.exclude;
137
- }
138
- return { host, include, exclude, keepAlive: proxy.keep_alive, agentTimeout };
139
- }
140
- catch {
141
- }
142
- }
143
- return null;
144
- }
145
- function closeTorrent(pid) {
146
- if (pid !== undefined) {
147
- const index = ARIA2.PID_QUEUE.findIndex(value => pid === value[0]);
148
- if (index !== -1) {
149
- ARIA2.PID_QUEUE.splice(index, 1);
150
- }
151
- }
152
- }
153
- function clearDnsLookup() {
154
- DNS.CACHE = Object.create(null);
155
- DNS.TIMEOUT.forEach(value => clearTimeout(value));
156
- DNS.TIMEOUT.length = 0;
157
- }
158
- function resetHttpHost(version) {
159
- switch (version) {
160
- case 1:
161
- for (const origin in HTTP.HOST) {
162
- HTTP.HOST[origin].version = 1;
163
- }
164
- break;
165
- case 2:
166
- for (const origin in HTTP.HOST) {
167
- const host = HTTP.HOST[origin];
168
- if (host.secure && host.version === 1) {
169
- const failed = host.failed(2, true);
170
- if (failed === 0 && host.failed(2, true) < 10 /* HOST.MAX_ERROR */ || failed < 3 /* HOST.MAX_FAILED */ && host.success(2, true) > 0) {
171
- host.version = version;
172
- }
173
- }
174
- }
175
- break;
176
- default:
177
- for (const origin in HTTP.HOST) {
178
- HTTP.HOST[origin].reset();
179
- }
180
- break;
181
- }
182
- }
183
- function validateCerts(certs) {
184
- const text = {};
185
- const file = {};
186
- const checkFile = (values) => {
187
- for (let pathname of values) {
188
- if (module_1.default.isPath(pathname = path.resolve(pathname))) {
189
- return pathname;
190
- }
191
- }
192
- };
193
- for (let origin in certs) {
194
- let { ca, cert, key, passphrase, version: minVersion } = certs[origin], file_ca, file_cert, file_key, keyObject;
195
- try {
196
- origin = new URL(origin).origin;
197
- }
198
- catch {
199
- continue;
200
- }
201
- if (ca) {
202
- if (!Array.isArray(ca)) {
203
- ca = [ca];
204
- }
205
- file_ca = checkFile(ca);
206
- ca = ca.map(value => Request.readCACert(value)).filter(value => value);
207
- if (ca.length === 1) {
208
- ca = ca[0];
209
- }
210
- else if (ca.length === 0) {
211
- ca = undefined;
212
- }
213
- }
214
- if (cert) {
215
- if (!Array.isArray(cert)) {
216
- cert = [cert];
217
- }
218
- file_cert = checkFile(cert);
219
- cert = cert.map(value => Request.readTLSCert(value)).filter(value => value);
220
- if (cert.length === 1) {
221
- cert = cert[0];
222
- }
223
- else if (cert.length === 0) {
224
- cert = undefined;
225
- key = undefined;
226
- }
227
- if (key) {
228
- if (!Array.isArray(key)) {
229
- key = [key];
230
- }
231
- file_key = checkFile(key);
232
- key = key.map(value => Request.readTLSKey(value)).filter(value => value);
233
- if (key.length) {
234
- if (!Array.isArray(passphrase)) {
235
- passphrase = passphrase ? [passphrase] : [];
236
- }
237
- keyObject = key.length > 1 || passphrase.length ? key.map((pem, index) => ({ pem, passphrase: passphrase[index] })) : key[0];
238
- }
239
- }
240
- }
241
- if (ca || cert) {
242
- text[origin] = { ca, cert, key: keyObject, version: minVersion };
243
- }
244
- if (file_ca || file_cert) {
245
- file[origin] = { ca: file_ca, cert: file_cert, key: file_key };
246
- }
247
- }
248
- return [text, file];
249
- }
250
- class Request extends module_1.default {
251
- static purgeMemory(percent = 1, limit = 0, parent) {
252
- if (percent >= 1) {
253
- resetHttpHost();
254
- clearDnsLookup();
255
- }
256
- else if (percent === 0) {
257
- clearDnsLookup();
258
- }
259
- else {
260
- resetHttpHost(2);
261
- }
262
- return parent ? super.purgeMemory(percent, limit) : Promise.resolve(0);
263
- }
264
- static loadSettings(settings, password) {
265
- if (!this.enabled("process.password" /* KEY_NAME.PROCESS_PASSWORD */) || super.loadSettings({ process: settings.process }, password)) {
266
- const { request, download } = settings;
267
- if (download && (0, types_1.isPlainObject)(download.aria2)) {
268
- let { bin, update_status, max_concurrent_downloads, max_connection_per_server, bt_stop_timeout, bt_tracker_connect_timeout, bt_tracker_timeout, min_split_size, disk_cache, lowest_speed_limit, always_resume, file_allocation, conf_path } = download.aria2;
269
- const parseSize = (value, zero) => {
270
- if (zero && (value === '0' || value === 0)) {
271
- return 0;
272
- }
273
- if ((0, types_1.isString)(value) && /^\d+[KM]$/.test(value = value.trim().toUpperCase())) {
274
- return value;
275
- }
276
- };
277
- if (bin === false) {
278
- ARIA2.BIN = '';
279
- }
280
- else if (bin && this.isPath(bin = path.resolve(bin), true)) {
281
- ARIA2.BIN = bin;
282
- }
283
- if ((0, types_1.isPlainObject)(update_status)) {
284
- const { interval, broadcast_only } = update_status;
285
- if (typeof broadcast_only === 'boolean') {
286
- ARIA2.UPDATE_BROADCAST_ONLY = broadcast_only;
287
- }
288
- update_status = interval;
289
- }
290
- if ((update_status = (0, util_1.asInt)(update_status)) >= 0) {
291
- ARIA2.UPDATE_STATUS = update_status;
292
- }
293
- if ((max_concurrent_downloads = (0, util_1.asInt)(max_concurrent_downloads)) > 0) {
294
- ARIA2.MAX_CONCURRENT_DOWNLOADS = max_concurrent_downloads;
295
- }
296
- if ((max_connection_per_server = (0, util_1.asInt)(max_connection_per_server)) > 0) {
297
- ARIA2.MAX_CONNECTION_PER_SERVER = max_connection_per_server;
298
- }
299
- if ((bt_stop_timeout = (0, util_1.asInt)(bt_stop_timeout)) >= 0) {
300
- ARIA2.BT_STOP_TIMEOUT = bt_stop_timeout;
301
- }
302
- if ((bt_tracker_connect_timeout = (0, util_1.asInt)(bt_tracker_connect_timeout)) > 0) {
303
- ARIA2.BT_TRACKER_CONNECT_TIMEOUT = bt_tracker_connect_timeout;
304
- }
305
- if ((bt_tracker_timeout = (0, util_1.asInt)(bt_tracker_timeout)) > 0) {
306
- ARIA2.BT_TRACKER_TIMEOUT = bt_tracker_timeout;
307
- }
308
- if (min_split_size = parseSize(min_split_size)) {
309
- ARIA2.MIN_SPLIT_SIZE = min_split_size;
310
- }
311
- if ((disk_cache = parseSize(disk_cache, true)) !== undefined) {
312
- ARIA2.DISK_CACHE = disk_cache;
313
- }
314
- if ((lowest_speed_limit = parseSize(lowest_speed_limit, true)) !== undefined) {
315
- ARIA2.LOWEST_SPEED_LIMIT = lowest_speed_limit;
316
- }
317
- if (always_resume) {
318
- ARIA2.ALWAYS_RESUME = always_resume;
319
- }
320
- if ((0, types_1.isString)(file_allocation)) {
321
- const value = file_allocation.toLowerCase();
322
- switch (value) {
323
- case 'none':
324
- case 'prealloc':
325
- case 'trunc':
326
- case 'falloc':
327
- ARIA2.FILE_ALLOCATION = value;
328
- break;
329
- }
330
- }
331
- if (conf_path && this.isPath(conf_path = path.resolve(conf_path))) {
332
- ARIA2.CONF_PATH = conf_path;
333
- }
334
- }
335
- if ((0, types_1.isPlainObject)(request)) {
336
- let { read_timeout, agent, use, headers, certs } = request, agent_timeout;
337
- if ((read_timeout = (0, util_1.fromSeconds)(read_timeout)) >= 0) {
338
- READ_TIMEOUT = read_timeout;
339
- }
340
- if ((0, types_1.isObject)(agent)) {
341
- let keep_alive;
342
- ({ keep_alive, timeout: agent_timeout } = agent);
343
- if ((agent_timeout = (0, util_1.fromSeconds)(agent_timeout)) > 0) {
344
- AGENT_TIMEOUT = agent_timeout;
345
- }
346
- else {
347
- agent_timeout = undefined;
348
- }
349
- if (typeof keep_alive === 'boolean') {
350
- KEEP_ALIVE = keep_alive;
351
- }
352
- else {
353
- keep_alive = undefined;
354
- }
355
- this.defineHttpAgent({ keepAlive: keep_alive, timeout: agent_timeout });
356
- }
357
- if ((0, types_1.isObject)(use)) {
358
- let { http_version, accept_encoding } = use;
359
- if (typeof accept_encoding === 'boolean') {
360
- ACCEPT_ENCODING = accept_encoding;
361
- }
362
- switch (http_version = (0, util_1.asInt)(http_version)) {
363
- case 1:
364
- case 2:
365
- HTTP.VERSION = http_version;
366
- break;
367
- }
368
- }
369
- if ((0, types_1.isObject)(headers)) {
370
- setOutgoingHeaders(HTTP.HEADERS, headers);
371
- }
372
- if ((0, types_1.isObject)(certs)) {
373
- [TLS.TEXT, TLS.FILE] = validateCerts(certs);
374
- }
375
- HTTP.PROXY = getProxySettings(request, agent_timeout);
376
- const time_format = request.settings?.time_format;
377
- switch (time_format) {
378
- case 'readable':
379
- case 'relative':
380
- case 'none':
381
- LOG_TIMEFORMAT = time_format;
382
- break;
383
- }
384
- LOG_HTTP = this.hasLogType(1024 /* LOG_TYPE.HTTP */);
385
- LOG_TIMEPROCESS = this.hasLogType(256 /* LOG_TYPE.TIME_PROCESS */);
386
- }
387
- return true;
388
- }
389
- return false;
390
- }
391
- static readCACert(value, cache) {
392
- return (0, types_1.isString)(value) ? (this.isCert(value) ? value : this.readText(value, cache)).trim() : '';
393
- }
394
- static readTLSCert(value, cache) {
395
- return this.readCACert(value, cache);
396
- }
397
- static readTLSKey(value, cache) {
398
- return this.readCACert(value, cache);
399
- }
400
- static isCert(value) {
401
- return (0, types_1.isString)(value) && (value = value.trim()) ? value.indexOf('\n') !== -1 && value.startsWith('---') && value.endsWith('---') : false;
402
- }
403
- static fromURL(url, value) {
404
- if (this.isURL(value)) {
405
- return value;
406
- }
407
- const auth = host_1.default.formatBasicAuth(url);
408
- return url.protocol + '//' + (auth && (auth + '@')) + url.hostname + (url.port ? ':' + url.port : '') + (value[0] !== '/' ? '/' : '') + value;
409
- }
410
- static fromStatusCode(value) {
411
- switch (+value) {
412
- case 100 /* HTTP_STATUS.CONTINUE */:
413
- return 'Continue';
414
- case 101 /* HTTP_STATUS.SWITCHING_PROTOCOL */:
415
- return 'Switching Protocol';
416
- case 102 /* HTTP_STATUS.PROCESSING */:
417
- return 'Processing';
418
- case 103 /* HTTP_STATUS.EARLY_HINTS */:
419
- return 'Early Hints';
420
- case 200 /* HTTP_STATUS.OK */:
421
- return 'OK';
422
- case 201 /* HTTP_STATUS.CREATED */:
423
- return 'Created';
424
- case 202 /* HTTP_STATUS.ACCEPTED */:
425
- return 'Accepted';
426
- case 203 /* HTTP_STATUS.NON_AUTHORITATIVE_INFORMATION */:
427
- return 'Non-Authoritative Information';
428
- case 204 /* HTTP_STATUS.NO_CONTENT */:
429
- return 'No Content';
430
- case 205 /* HTTP_STATUS.RESET_CONTENT */:
431
- return 'Reset Content';
432
- case 206 /* HTTP_STATUS.PARTIAL_CONTENT */:
433
- return 'Partial Content';
434
- case 300 /* HTTP_STATUS.MULTIPLE_CHOICES */:
435
- return 'Multiple Choice';
436
- case 301 /* HTTP_STATUS.MOVED_PERMANENTLY */:
437
- return 'Moved Permanently';
438
- case 302 /* HTTP_STATUS.FOUND */:
439
- return 'Found';
440
- case 303 /* HTTP_STATUS.SEE_OTHER */:
441
- return 'See Other';
442
- case 304 /* HTTP_STATUS.NOT_MODIFIED */:
443
- return 'Not Modified';
444
- case 305 /* HTTP_STATUS.USE_PROXY */:
445
- return 'Use Proxy';
446
- case 307 /* HTTP_STATUS.TEMPORARY_REDIRECT */:
447
- return 'Temporary Redirect';
448
- case 308 /* HTTP_STATUS.PERMANENT_REDIRECT */:
449
- return 'Permanent Redirect';
450
- case 400 /* HTTP_STATUS.BAD_REQUEST */:
451
- return 'Bad Request';
452
- case 401 /* HTTP_STATUS.UNAUTHORIZED */:
453
- return 'Upgrade Required';
454
- case 402 /* HTTP_STATUS.PAYMENT_REQUIRED */:
455
- return 'Payment Required';
456
- case 403 /* HTTP_STATUS.FORBIDDEN */:
457
- return 'Forbidden';
458
- case 404 /* HTTP_STATUS.NOT_FOUND */:
459
- return 'Not Found';
460
- case 405 /* HTTP_STATUS.METHOD_NOT_ALLOWED */:
461
- return 'Method Not Allowed';
462
- case 406 /* HTTP_STATUS.NOT_ACCEPTABLE */:
463
- return 'Not Acceptable';
464
- case 407 /* HTTP_STATUS.PROXY_AUTHENTICATION_REQUIRED */:
465
- return 'Proxy Authentication Required';
466
- case 408 /* HTTP_STATUS.REQUEST_TIMEOUT */:
467
- return 'Request Timeout';
468
- case 409 /* HTTP_STATUS.CONFLICT */:
469
- return 'Conflict';
470
- case 410 /* HTTP_STATUS.GONE */:
471
- return 'Gone';
472
- case 411 /* HTTP_STATUS.LENGTH_REQUIRED */:
473
- return 'Length Required';
474
- case 412 /* HTTP_STATUS.PRECONDITION_FAILED */:
475
- return 'Precondition Failed';
476
- case 413 /* HTTP_STATUS.PAYLOAD_TOO_LARGE */:
477
- return 'Payload Too Large';
478
- case 414 /* HTTP_STATUS.REQUEST_URI_TOO_LONG */:
479
- return 'URI Too Long';
480
- case 415 /* HTTP_STATUS.UNSUPPORTED_MEDIA_TYPE */:
481
- return 'Unsupported Media Type';
482
- case 416 /* HTTP_STATUS.RANGE_NOT_SATISFIABLE */:
483
- return 'Range Not Satisfiable';
484
- case 417 /* HTTP_STATUS.EXPECTATION_FAILED */:
485
- return 'Expectation Failed';
486
- case 421 /* HTTP_STATUS.MISDIRECTED_REQUEST */:
487
- return 'Misdirected Request';
488
- case 422 /* HTTP_STATUS.UNPROCESSABLE_ENTITY */:
489
- return 'Unprocessable Entity';
490
- case 423 /* HTTP_STATUS.LOCKED */:
491
- return 'Locked';
492
- case 424 /* HTTP_STATUS.FAILED_DEPENDENCY */:
493
- return 'Failed Dependency';
494
- case 426 /* HTTP_STATUS.UPGRADE_REQUIRED */:
495
- return 'Upgrade Required';
496
- case 428 /* HTTP_STATUS.PRECONDITION_REQUIRED */:
497
- return 'Precondition Required';
498
- case 429 /* HTTP_STATUS.TOO_MANY_REQUESTS */:
499
- return 'Too Many Requests';
500
- case 431 /* HTTP_STATUS.REQUEST_HEADER_FIELDS_TOO_LARGE */:
501
- return 'Request Header Fields Too Large';
502
- case 451 /* HTTP_STATUS.UNAVAILABLE_FOR_LEGAL_REASONS */:
503
- return 'Unavailable For Legal Reasons';
504
- case 500 /* HTTP_STATUS.INTERNAL_SERVER_ERROR */:
505
- return 'Internal Server Error';
506
- case 501 /* HTTP_STATUS.NOT_IMPLEMENTED */:
507
- return 'Not Implemented';
508
- case 502 /* HTTP_STATUS.BAD_GATEWAY */:
509
- return 'Bad Gateway';
510
- case 503 /* HTTP_STATUS.SERVICE_UNAVAILABLE */:
511
- return 'Service Unavailable';
512
- case 504 /* HTTP_STATUS.GATEWAY_TIMEOUT */:
513
- return 'Gateway Timeout';
514
- case 505 /* HTTP_STATUS.HTTP_VERSION_NOT_SUPPORTED */:
515
- return 'HTTP Version Not Supported';
516
- case 506 /* HTTP_STATUS.VARIANT_ALSO_NEGOTIATES */:
517
- return 'Variant Also Negotiates';
518
- case 507 /* HTTP_STATUS.INSUFFICIENT_STORAGE */:
519
- return 'Insufficient Storage';
520
- case 508 /* HTTP_STATUS.LOOP_DETECTED */:
521
- return 'Loop Detected';
522
- case 510 /* HTTP_STATUS.NOT_EXTENDED */:
523
- return 'Not Extended';
524
- case 511 /* HTTP_STATUS.NETWORK_AUTHENTICATION_REQUIRED */:
525
- return 'Network Authentication Required';
526
- default:
527
- return "Unknown" /* ERR_MESSAGE.UNKNOWN */;
528
- }
529
- }
530
- static defineHttpAgent(options) {
531
- const { keepAlive, timeout = 0 } = options;
532
- if (options.http instanceof http.Agent) {
533
- http.globalAgent = options.http;
534
- }
535
- else if (timeout > 0) {
536
- http.globalAgent = new http.Agent({ keepAlive, timeout });
537
- }
538
- else if (typeof keepAlive === 'boolean') {
539
- http.globalAgent = new http.Agent({ keepAlive });
540
- }
541
- if (options.https instanceof https.Agent) {
542
- https.globalAgent = options.https;
543
- }
544
- else if (timeout > 0) {
545
- https.globalAgent = new https.Agent({ keepAlive, timeout });
546
- }
547
- else if (typeof keepAlive === 'boolean') {
548
- https.globalAgent = new https.Agent({ keepAlive });
549
- }
550
- }
551
- static defineDnsLookup({ family, expires, resolve }, reset) {
552
- if (reset) {
553
- clearDnsLookup();
554
- }
555
- switch (family = (0, util_1.asInt)(family)) {
556
- case 0:
557
- case 4:
558
- case 6:
559
- DNS.FAMILY = family;
560
- break;
561
- }
562
- if (expires !== undefined) {
563
- if (typeof expires === 'string') {
564
- expires = (0, types_1.parseExpires)(expires);
565
- }
566
- if (expires >= 0) {
567
- DNS.EXPIRES = expires !== Infinity ? Math.min(expires, this.MAX_TIMEOUT) : Infinity;
568
- }
569
- }
570
- for (const hostname in resolve) {
571
- let { address, family: ipv } = resolve[hostname];
572
- if (address && (ipv = ipv && ((ipv = +ipv) === 4 || ipv === 6) ? ipv : net.isIPv6(address) ? 6 : net.isIPv4(address) ? 4 : 0)) {
573
- DNS.CACHE[hostname] = [address, ipv];
574
- }
575
- }
576
- }
577
- static getAria2Path() {
578
- return ARIA2.BIN;
579
- }
580
- constructor(data) {
581
- super();
582
- this.startTime = Date.now();
583
- this.readExpect = 'none';
584
- this.proxy = null;
585
- this._moduleName = "request" /* VALUES.MODULE */;
586
- this._config = {
587
- timeout: 60000 /* TIME.m */,
588
- connectTimeout: 20 * 1000 /* TIME.S */,
589
- redirectLimit: 10,
590
- retryWait: 1000 /* TIME.S */,
591
- retryAfter: 30 * 1000 /* TIME.S */,
592
- retryLimit: 5
593
- };
594
- this[_a] = false;
595
- this[_b] = null;
596
- this[_c] = null;
597
- this[_d] = null;
598
- this[_e] = Object.create(null);
599
- this[_f] = Object.create(null);
600
- this[_g] = [{}, {}];
601
- this[_h] = new Set();
602
- this[_j] = {};
603
- this[_k] = [Object.create(null)];
604
- if ((0, types_1.isPlainObject)(data)) {
605
- const { headers, read_timeout, agent, use, connect, certs } = data;
606
- const timeout = (0, util_1.fromSeconds)(data.timeout);
607
- let value;
608
- this.readTimeout = (value = (0, util_1.fromSeconds)(read_timeout)) >= 0 ? value : READ_TIMEOUT;
609
- this.keepAlive = typeof (value = agent?.keep_alive) === 'boolean' ? value : KEEP_ALIVE;
610
- this.acceptEncoding = typeof (value = use?.accept_encoding) === 'boolean' ? value : ACCEPT_ENCODING;
611
- switch (value = (0, util_1.asInt)(use?.http_version)) {
612
- case 1:
613
- case 2:
614
- this[kHttpVersion] = value;
615
- break;
616
- }
617
- this[kIpVersion] = (value = (0, util_1.asInt)(data.dns?.family)) && (value === 4 || value === 6) ? value : 0;
618
- if ((value = (0, util_1.fromSeconds)(agent?.timeout)) >= 0) {
619
- this[kAgentTimeout] = value;
620
- }
621
- else {
622
- this[kAgentTimeout] = AGENT_TIMEOUT;
623
- value = undefined;
624
- }
625
- const proxy = getProxySettings(data, value);
626
- if (proxy) {
627
- this.proxy = proxy;
628
- }
629
- if ((0, types_1.isObject)(headers)) {
630
- setOutgoingHeaders(this[kHeaders] = {}, headers);
631
- }
632
- if ((0, types_1.isObject)(certs)) {
633
- this[kCerts] = validateCerts(certs);
634
- }
635
- if ((0, types_1.isObject)(connect)) {
636
- this.apply({ client: {
637
- timeout,
638
- connectTimeout: (0, util_1.fromSeconds)(connect.timeout),
639
- redirectLimit: (0, util_1.asInt)(connect.redirect_limit),
640
- retryWait: (0, util_1.fromSeconds)(connect.retry_wait),
641
- retryAfter: (0, util_1.fromSeconds)(connect.retry_after),
642
- retryLimit: (0, util_1.asInt)(connect.retry_limit)
643
- } });
644
- }
645
- else if (timeout >= 0) {
646
- this.apply({ client: { timeout } });
647
- }
648
- }
649
- else {
650
- data = {};
651
- this.readTimeout = READ_TIMEOUT;
652
- this.keepAlive = KEEP_ALIVE;
653
- this.acceptEncoding = ACCEPT_ENCODING;
654
- this[kAgentTimeout] = AGENT_TIMEOUT;
655
- this[kIpVersion] = DNS.FAMILY;
656
- }
657
- this.module = data;
658
- }
659
- flushLog() {
660
- if (this[kSingleton]) {
661
- this._logQueued.length = 0;
662
- if (LOG_HTTP) {
663
- this[kConnectHttp] = [{}, {}];
664
- }
665
- return;
666
- }
667
- if (LOG_HTTP) {
668
- const log = this._logQueued;
669
- const output = [];
670
- let count = 0;
671
- this[kConnectHttp].forEach((protocol, index) => {
672
- const title = 'HTTP' + (index + 1);
673
- for (const origin in protocol) {
674
- const value = protocol[origin];
675
- const args = [];
676
- for (let i = 0; i < log.length; ++i) {
677
- const item = log[i];
678
- if (Array.isArray(item[2]) && item[2][0].startsWith(origin)) {
679
- item[1] = '';
680
- item[2][0] = item[2][0].substring(origin.length);
681
- item[4].titleBgColor = undefined;
682
- item[4].titleJustify = 'right';
683
- args.push(item);
684
- log.splice(i--, 1);
685
- }
686
- }
687
- output.push([title, origin, value, args]);
688
- count = Math.max(count, value);
689
- }
690
- });
691
- if (!this.host?.aborted) {
692
- output.sort((a, b) => b[2] - a[2]);
693
- const width = count.toString().length;
694
- output.forEach(item => {
695
- const [title, origin, downloads, messages] = item;
696
- const options = { ...title === 'HTTP1' ? module_1.default.LOG_STYLE_NOTICE : module_1.default.LOG_STYLE_INFO };
697
- if (messages.length === 1) {
698
- const message = messages[0];
699
- message[1] = title;
700
- message[2] = [origin + message[2][0], message[2][1]];
701
- message[4] = Object.assign(message[4], options);
702
- module_1.default.formatMessage(...message);
703
- }
704
- else {
705
- this.formatMessage(1024 /* LOG_TYPE.HTTP */, title, [origin, 'downloads: ' + downloads.toString().padStart(width)], '', options);
706
- messages.forEach(args => {
707
- args[4].titleIndent = true;
708
- module_1.default.formatMessage(...args);
709
- });
710
- }
711
- });
712
- }
713
- this[kConnectHttp] = [{}, {}];
714
- }
715
- super.flushLog();
716
- }
717
- detach(singleton) {
718
- if (typeof singleton === 'boolean') {
719
- this[kSingleton] = singleton;
720
- }
721
- if (singleton !== false) {
722
- super.detach();
723
- }
724
- }
725
- abort() {
726
- this[kDownloading].forEach(item => item.abort());
727
- this.close();
728
- if (!this[kSingleton]) {
729
- super.abort();
730
- }
731
- }
732
- init(config) {
733
- if (config) {
734
- const { headers, httpVersion, ipVersion, requestTimeout } = config;
735
- if ((0, types_1.isObject)(headers)) {
736
- setOutgoingHeaders(this[kHeaders] || (this[kHeaders] = {}), headers);
737
- }
738
- if (httpVersion !== undefined) {
739
- this.httpVersion = httpVersion;
740
- }
741
- if (ipVersion !== undefined) {
742
- this.ipVersion = ipVersion;
743
- }
744
- if (requestTimeout !== undefined) {
745
- this.readTimeout = (0, util_1.fromSeconds)(requestTimeout);
746
- }
747
- }
748
- return this;
749
- }
750
- apply(options) {
751
- for (const name in options) {
752
- const value = options[name];
753
- switch (name) {
754
- case 'client': {
755
- const { timeout, connectTimeout, redirectLimit, retryWait, retryAfter, retryLimit } = value;
756
- if (timeout >= 0) {
757
- this._config.timeout = timeout;
758
- }
759
- if (connectTimeout >= 0) {
760
- this._config.connectTimeout = connectTimeout;
761
- }
762
- if (redirectLimit >= 0) {
763
- this._config.redirectLimit = redirectLimit;
764
- }
765
- if (retryWait >= 0) {
766
- this._config.retryWait = Math.min(retryWait, 600 * 1000 /* TIME.S */);
767
- }
768
- if (retryAfter >= 0) {
769
- this._config.retryAfter = Math.min(retryAfter, module_1.default.MAX_TIMEOUT);
770
- }
771
- if (retryLimit >= 0) {
772
- this._config.retryLimit = retryLimit;
773
- }
774
- break;
775
- }
776
- case 'httpVersion':
777
- case 'ipVersion':
778
- if (typeof value === 'number') {
779
- this[name] = value;
780
- }
781
- break;
782
- case 'acceptEncoding':
783
- case 'keepAlive':
784
- if (typeof value === 'boolean') {
785
- this[name] = value;
786
- }
787
- break;
788
- case 'readExpect':
789
- if ((0, types_1.isString)(value)) {
790
- this[name] = value;
791
- }
792
- break;
793
- }
794
- }
795
- return this;
796
- }
797
- addDns(hostname, address, family) {
798
- if (!this[kConnectDns][hostname]) {
799
- switch (family) {
800
- case 'IPv4':
801
- family = 4;
802
- break;
803
- case 'IPv6':
804
- family = 6;
805
- break;
806
- default:
807
- if (net.isIPv4(address)) {
808
- family = 4;
809
- }
810
- else if (net.isIPv6(address)) {
811
- family = 6;
812
- }
813
- else {
814
- return;
815
- }
816
- break;
817
- }
818
- setDnsCache(hostname, this[kConnectDns][hostname] = [address, family]);
819
- }
820
- }
821
- lookupDns(hostname) {
822
- var _l;
823
- const resolved = this[kConnectDns][hostname] || DNS.CACHE[hostname];
824
- if (resolved) {
825
- return (...args) => args[2](null, ...resolved);
826
- }
827
- const pending = (_l = this[kPendingDns])[hostname] || (_l[hostname] = []);
828
- return (value, options, callback) => {
829
- if (pending.push(callback) === 1) {
830
- const configure = (family) => family === 0 ? options : { family, hints: family === 6 ? dns.V4MAPPED : 0 };
831
- const success = (connected) => {
832
- setDnsCache(value, this[kConnectDns][value] = connected);
833
- pending.forEach(cb => cb(null, ...connected));
834
- pending.length = 0;
835
- };
836
- const failed = (err) => {
837
- pending.forEach(cb => cb(err, '', 0));
838
- pending.length = 0;
839
- };
840
- let ipVersion = this.ipVersion;
841
- dns.lookup(value, configure(ipVersion), (err, address, family) => {
842
- if (!err) {
843
- success([address, family]);
844
- }
845
- else {
846
- switch (err.code) {
847
- case 'ENOTFOUND':
848
- case 'EBADNAME':
849
- case 'ENODATA':
850
- failed(err);
851
- return;
852
- case 'ETIMEOUT':
853
- case 'ECONNREFUSED':
854
- case 'ESERVFAIL':
855
- case 'EFILE':
856
- ipVersion = 0;
857
- break;
858
- default:
859
- if (ipVersion === 0) {
860
- failed(err);
861
- return;
862
- }
863
- ipVersion = ipVersion === 4 ? 6 : 4;
864
- break;
865
- }
866
- dns.lookup(value, configure(ipVersion), (err, address, family) => {
867
- if (!err) {
868
- success([address, family]);
869
- }
870
- else {
871
- failed(err);
872
- }
873
- });
874
- }
875
- });
876
- }
877
- };
878
- }
879
- proxyOf(uri, localhost) {
880
- const proxy = this.proxy || this.host && HTTP.PROXY;
881
- if (proxy) {
882
- const { include, exclude } = proxy;
883
- if (!include && !exclude && !localhost) {
884
- return proxy;
885
- }
886
- if ((0, types_1.isArray)(include)) {
887
- return include.some(value => uri.startsWith(value)) ? proxy : undefined;
888
- }
889
- if (Array.isArray(exclude) && !exclude.some(value => uri.startsWith(value))) {
890
- return proxy;
891
- }
892
- }
893
- }
894
- headersOf(uri) {
895
- const headers = this[kHeaders];
896
- return headers && getBaseHeaders(uri, headers) || (this.host ? getBaseHeaders(uri, HTTP.HEADERS) : undefined);
897
- }
898
- aria2c(uri, options) {
899
- if (!ARIA2.BIN) {
900
- return Promise.reject((0, types_1.errorMessage)("aria2" /* VALUES.ARIA2 */, "Binary not found" /* ERR_MESSAGE.NOTFOUND_BINARY */));
901
- }
902
- if (typeof uri === 'string' && module_1.default.isURL(uri)) {
903
- try {
904
- uri = new URL(uri);
905
- }
906
- catch (err) {
907
- return Promise.reject(err);
908
- }
909
- }
910
- let pathname, headers, binOpts, silent;
911
- if (options) {
912
- if (typeof options === 'string') {
913
- pathname = options;
914
- }
915
- else {
916
- ({ pathname, headers, binOpts, silent } = options);
917
- if ((0, types_1.isArray)(binOpts)) {
918
- let next = false;
919
- binOpts = binOpts.filter(opt => !((0, types_1.isString)(opt) && /^-[a-z][\S\s]*$/i.test(opt.trim()))).map((opt) => {
920
- if (next) {
921
- if (!module_1.default.asString(opt).startsWith('--')) {
922
- return [];
923
- }
924
- next = false;
925
- }
926
- switch (typeof opt) {
927
- case 'string': {
928
- const value = opt.trim();
929
- if (value.startsWith('--')) {
930
- const match = /^(--[a-z]+[a-z0-9-]*)(=)?\s*(.*)$/.exec(value);
931
- if (match) {
932
- switch (match[1]) {
933
- case '--daemon':
934
- case '--version':
935
- case '--help':
936
- break;
937
- case '--input-file':
938
- if (!match[2]) {
939
- next = true;
940
- }
941
- break;
942
- default:
943
- return match[3] ? [match[1], module_1.default.sanitizeArgs(match[3])] : [match[1]];
944
- }
945
- }
946
- }
947
- else if (value) {
948
- return [module_1.default.sanitizeArgs(value)];
949
- }
950
- break;
951
- }
952
- case 'number':
953
- case 'boolean':
954
- return [opt.toString()];
955
- default:
956
- if ((0, types_1.isArray)(opt)) {
957
- return opt.filter(item => (0, types_1.isString)(item)).map((item) => module_1.default.sanitizeArgs(item));
958
- }
959
- break;
960
- }
961
- return [];
962
- }).flat();
963
- }
964
- }
965
- }
966
- if (!(0, types_1.isString)(pathname)) {
967
- if (this.host) {
968
- return Promise.reject((0, types_1.errorMessage)("aria2" /* VALUES.ARIA2 */, "Invalid parameters" /* ERR_MESSAGE.PARAMETERS */, 'pathname'));
969
- }
970
- pathname = process.cwd();
971
- }
972
- if ((this.host || this.hasOwnPermission()) && !this.canWrite(pathname = path.resolve(pathname.trim()))) {
973
- return Promise.reject((0, types_1.errorMessage)("aria2" /* VALUES.ARIA2 */, "Unsupported access" /* ERR_MESSAGE.UNSUPPORTED_ACCESS */, pathname));
974
- }
975
- if (!module_1.default.createDir(pathname)) {
976
- return Promise.reject((0, types_1.errorMessage)("aria2" /* VALUES.ARIA2 */, "Path is not a directory" /* ERR_MESSAGE.NOT_DIRECTORY */, pathname));
977
- }
978
- silent ?? (silent = this[kSingleton]);
979
- return new Promise((resolve, reject) => {
980
- let protocol, origin, username, password;
981
- if (uri instanceof URL) {
982
- ({ protocol, origin, username, password, href: uri } = uri);
983
- }
984
- const escapeQuote = (value) => {
985
- value = value.replace(/"/g, '\\"');
986
- return PLATFORM_WIN32 ? value : value.replace(/[ $`]/g, capture => (capture !== ' ' ? '\\' : '') + '\\' + capture);
987
- };
988
- const init = [
989
- `--dir="${escapeQuote(pathname)}"`,
990
- '--download-result=full',
991
- '--follow-torrent=mem',
992
- '--follow-metalink=mem',
993
- '--seed-time=0',
994
- '--max-overall-upload-limit=1K',
995
- '--bt-max-peers=1',
996
- '--allow-overwrite=true',
997
- '--dry-run=false',
998
- '--enable-color=false',
999
- '--daemon=false',
1000
- '--stderr=false',
1001
- '--log=""'
1002
- ];
1003
- let args = [];
1004
- if ((0, types_1.isArray)(binOpts)) {
1005
- for (let i = 0; i < binOpts.length; ++i) {
1006
- const leading = binOpts[i] + '=';
1007
- for (const arg of init) {
1008
- if (arg.startsWith(leading)) {
1009
- const items = [];
1010
- for (let k = i + 1; k < binOpts.length; ++k) {
1011
- const next = binOpts[k];
1012
- if (next.startsWith('--')) {
1013
- break;
1014
- }
1015
- items.push(next);
1016
- }
1017
- const l = items.length + 1;
1018
- binOpts.splice(i, l);
1019
- i += l;
1020
- break;
1021
- }
1022
- }
1023
- }
1024
- }
1025
- else {
1026
- binOpts = undefined;
1027
- }
1028
- const { connectTimeout, timeout, retryWait, retryLimit } = this._config;
1029
- const opts = [
1030
- '--log-level=warn',
1031
- '--bt-stop-timeout=' + ARIA2.BT_STOP_TIMEOUT,
1032
- '--bt-tracker-connect-timeout=' + ARIA2.BT_TRACKER_CONNECT_TIMEOUT,
1033
- '--bt-tracker-timeout=' + ARIA2.BT_TRACKER_TIMEOUT,
1034
- '--file-allocation=' + ARIA2.FILE_ALLOCATION,
1035
- '--max-tries=' + (retryLimit + 1)
1036
- ];
1037
- const ignoreOpt = (...values) => !binOpts?.some(item => values.includes(item));
1038
- if (ARIA2.MAX_CONCURRENT_DOWNLOADS) {
1039
- opts.push('--max-concurrent-downloads=' + ARIA2.MAX_CONCURRENT_DOWNLOADS);
1040
- }
1041
- if (ARIA2.MAX_CONNECTION_PER_SERVER) {
1042
- opts.push('--max-connection-per-server=' + ARIA2.MAX_CONNECTION_PER_SERVER);
1043
- }
1044
- if (ARIA2.MIN_SPLIT_SIZE) {
1045
- opts.push('--min-split-size=' + ARIA2.MIN_SPLIT_SIZE);
1046
- }
1047
- if (ARIA2.DISK_CACHE !== null) {
1048
- opts.push('--disk-cache=' + ARIA2.DISK_CACHE);
1049
- }
1050
- if (ARIA2.LOWEST_SPEED_LIMIT !== null) {
1051
- opts.push('--lowest-speed-limit=' + ARIA2.LOWEST_SPEED_LIMIT);
1052
- }
1053
- if (ARIA2.CONF_PATH) {
1054
- opts.push(`--conf-path="${escapeQuote(ARIA2.CONF_PATH)}"`);
1055
- }
1056
- if (!ARIA2.ALWAYS_RESUME) {
1057
- opts.push('--always-resume=false', '--keep-unfinished-download-result=false');
1058
- }
1059
- if (connectTimeout > 0) {
1060
- opts.push('--connect-timeout=' + Math.min(Math.ceil(connectTimeout / 1000), 600));
1061
- }
1062
- if (timeout > 0) {
1063
- opts.push('--timeout=' + Math.min(Math.ceil(timeout / 1000), 600));
1064
- }
1065
- if (retryWait > 0) {
1066
- opts.push('--retry-wait=' + Math.min(Math.ceil(retryWait / 1000), 600));
1067
- }
1068
- if (protocol) {
1069
- if (this.agentTimeout === 0) {
1070
- opts.push('--enable-http-keep-alive=false');
1071
- }
1072
- const baseHeaders = ignoreOpt('--header') && this.headersOf(uri);
1073
- if (headers || baseHeaders) {
1074
- if (baseHeaders) {
1075
- headers = headers ? { ...baseHeaders, ...headers } : baseHeaders;
1076
- }
1077
- for (const name in headers) {
1078
- let items = headers[name];
1079
- if (!Array.isArray(items)) {
1080
- items = [items.toString()];
1081
- }
1082
- args.push(...items.map(value => `--header="${name}: ${escapeQuote(value)}"`));
1083
- }
1084
- }
1085
- if (origin) {
1086
- const secure = this[kCerts]?.[1][origin] || (this.host ? TLS.FILE[origin] : null);
1087
- if (secure) {
1088
- if (secure.ca && ignoreOpt('--ca-certificate')) {
1089
- args.push(`--ca-certificate="${escapeQuote(secure.ca)}"`);
1090
- }
1091
- if (secure.cert && ignoreOpt('--certificate', '--private-key')) {
1092
- args.push(`--certificate="${escapeQuote(secure.cert)}"`);
1093
- if (secure.key) {
1094
- args.push(`--private-key="${escapeQuote(secure.key)}"`);
1095
- }
1096
- }
1097
- }
1098
- }
1099
- switch (protocol = protocol.substring(0, protocol.length - 1)) {
1100
- case 'ftp':
1101
- case 'http':
1102
- case 'https': {
1103
- const prefix = protocol === 'https' ? 'http' : protocol;
1104
- if (ignoreOpt(`--${prefix}-user`, `--${prefix}-passwd`)) {
1105
- if (username) {
1106
- args.push(`--${prefix}-user="${escapeQuote(decodeURIComponent(username))}"`);
1107
- }
1108
- if (password) {
1109
- args.push(`--${prefix}-passwd="${escapeQuote(decodeURIComponent(password))}"`);
1110
- }
1111
- }
1112
- const proxy = this.proxyOf(uri);
1113
- if (proxy && ignoreOpt(`--${protocol}-proxy-user`, `--${protocol}-proxy-passwd`)) {
1114
- ({ origin, username, password } = proxy.host);
1115
- if (ignoreOpt(`--${protocol}-proxy`)) {
1116
- args.push(`--${protocol}-proxy="${origin}"`);
1117
- }
1118
- if (username) {
1119
- args.push(`--${protocol}-proxy-user="${escapeQuote(decodeURIComponent(username))}"`);
1120
- }
1121
- if (password) {
1122
- args.push(`--${protocol}-proxy-passwd="${escapeQuote(decodeURIComponent(password))}"`);
1123
- }
1124
- }
1125
- break;
1126
- }
1127
- }
1128
- }
1129
- if (binOpts) {
1130
- for (const leading of binOpts) {
1131
- for (let i = 0; i < opts.length; ++i) {
1132
- if (opts[i].startsWith(leading)) {
1133
- opts.splice(i--, i);
1134
- break;
1135
- }
1136
- }
1137
- }
1138
- args = binOpts.concat(args);
1139
- }
1140
- if (args.length && module_1.default.hasLogType(32768 /* LOG_TYPE.STDOUT */)) {
1141
- this.formatMessage(32768 /* LOG_TYPE.STDOUT */, 'ARIA2', ARIA2.BIN, args.join(' '), { ...module_1.default.LOG_STYLE_WARN });
1142
- }
1143
- opts.push(`"${escapeQuote(uri)}"`);
1144
- args = args.concat(init, opts);
1145
- const startTime = Date.now();
1146
- let out = '', message = '', aborted;
1147
- const errorResponse = (pid, err) => {
1148
- aborted = true;
1149
- closeTorrent(pid);
1150
- reject(err);
1151
- };
1152
- const { pid, stdout, stderr } = child_process.spawn(module_1.default.sanitizeCmd(ARIA2.BIN), args, { cwd: pathname, shell: true, signal: this.signal })
1153
- .on('exit', code => {
1154
- closeTorrent(pid);
1155
- if (aborted) {
1156
- return;
1157
- }
1158
- if (this.aborted) {
1159
- errorResponse(pid, (0, types_1.createAbortError)());
1160
- return;
1161
- }
1162
- if (!code) {
1163
- const currentTime = Date.now();
1164
- const pattern = /\|(OK|ERR|INPR)\s*\|\s*([^|]+)\|\s*(\d+)\|([^\n]+)/g;
1165
- const result = [];
1166
- let messageUnit, match;
1167
- while (match = pattern.exec(out)) {
1168
- if (match[4].startsWith('[MEMORY]')) {
1169
- continue;
1170
- }
1171
- const file = path.normalize(match[4].trim());
1172
- switch (match[1]) {
1173
- case 'OK':
1174
- if (match[3] === '100') {
1175
- result.push(file);
1176
- }
1177
- messageUnit || (messageUnit = match[2]);
1178
- break;
1179
- case 'INPR':
1180
- if (ARIA2.ALWAYS_RESUME) {
1181
- break;
1182
- }
1183
- case 'ERR':
1184
- fs.unlink(file, err => err && !silent && !this[kSingleton] && this.writeFail(["Unable to delete file" /* ERR_MESSAGE.DELETE_FILE */, path.basename(file)], err, { type: 32 /* LOG_TYPE.FILE */, fatal: false }));
1185
- break;
1186
- }
1187
- }
1188
- if (result.length && !silent && LOG_HTTP && LOG_TIMEPROCESS) {
1189
- this.writeTimeProcess("aria2" /* VALUES.ARIA2 */, uri, startTime, { type: 1024 /* LOG_TYPE.HTTP */, queue: true, messageUnit, messageUnitMinWidth: 9 });
1190
- }
1191
- this.addLog(result.length ? types_1.STATUS_TYPE.INFO : types_1.STATUS_TYPE.ERROR, out, currentTime, currentTime - startTime, "aria2" /* VALUES.ARIA2 */, uri);
1192
- resolve(result);
1193
- }
1194
- else {
1195
- reject((0, types_1.errorValue)(message || "Unknown" /* ERR_MESSAGE.UNKNOWN */, 'Exit status: ' + code));
1196
- }
1197
- })
1198
- .on('error', err => errorResponse(pid, err));
1199
- stdout.setEncoding('utf-8').on('data', (value) => out += value);
1200
- stderr.setEncoding('utf-8').on('data', (value) => message += value);
1201
- if (pid !== undefined && module_1.default.isFile(uri, 'torrent')) {
1202
- if (!ARIA2.PID_TIMER) {
1203
- const clearTimer = () => {
1204
- clearInterval(ARIA2.PID_TIMER);
1205
- ARIA2.PID_TIMER = null;
1206
- };
1207
- ARIA2.PID_TIMER = setInterval(() => {
1208
- if (ARIA2.PID_QUEUE.length === 0) {
1209
- clearTimer();
1210
- return;
1211
- }
1212
- for (const item of ARIA2.PID_QUEUE) {
1213
- try {
1214
- process.kill(item[0], 0);
1215
- }
1216
- catch {
1217
- closeTorrent(item[0]);
1218
- }
1219
- }
1220
- if (ARIA2.UPDATE_STATUS && !silent) {
1221
- const item = ARIA2.PID_QUEUE.shift();
1222
- if (item) {
1223
- const broadcastId = item[2];
1224
- if (!ARIA2.UPDATE_BROADCAST_ONLY || broadcastId) {
1225
- let progressBar;
1226
- if (item[2]) {
1227
- progressBar = true;
1228
- }
1229
- else {
1230
- const current = (0, types_1.getLogCurrent)();
1231
- progressBar = current?.type === 128 /* LOG_TYPE.TIME_ELAPSED */ && current.title === "aria2" /* VALUES.ARIA2 */;
1232
- }
1233
- this.formatMessage(128 /* LOG_TYPE.TIME_ELAPSED */, "aria2" /* VALUES.ARIA2 */, ['Downloading...', (0, types_1.formatTime)(startTime, true)], (PLATFORM_WIN32 ? 'taskkill /f /pid' : 'kill') + ` ${item[0]} -> ` + item[1], { ...module_1.default.LOG_STYLE_INFO, progressBar, broadcastId });
1234
- }
1235
- ARIA2.PID_QUEUE.push(item);
1236
- }
1237
- else {
1238
- clearTimer();
1239
- }
1240
- }
1241
- }, (ARIA2.UPDATE_STATUS || 30) * 1000 /* TIME.S */);
1242
- }
1243
- ARIA2.PID_QUEUE.push([pid, uri, this.broadcastId || undefined]);
1244
- }
1245
- });
1246
- }
1247
- json(uri, options = {}) {
1248
- options.format = 'json';
1249
- return this.get(uri, options);
1250
- }
1251
- pipe(uri, to, options = {}) {
1252
- options.pipeTo = to;
1253
- return this.get(uri, options);
1254
- }
1255
- opts(url, options) {
1256
- var _l, _m, _o, _p;
1257
- if (typeof url === 'string') {
1258
- url = new URL(url);
1259
- }
1260
- let host;
1261
- if (this.host) {
1262
- host = (_l = HTTP.HOST)[_m = url.origin] || (_l[_m] = new host_1.default(url, HTTP.VERSION));
1263
- }
1264
- else {
1265
- host = (_o = this[kHostInfo])[_p = url.origin] || (_o[_p] = new host_1.default(url, this.httpVersion || 1));
1266
- }
1267
- return { ...options, host, url };
1268
- }
1269
- open(uri, options) {
1270
- var _l, _m;
1271
- let { host, url, httpVersion, method = 'GET', encoding, format, headers, postData, keepAlive, agentTimeout, socketPath, timeout = this._config.connectTimeout, outStream } = options;
1272
- const getting = method === 'GET';
1273
- const posting = method === 'POST';
1274
- if (format) {
1275
- let parser;
1276
- if ((0, types_1.isObject)(format)) {
1277
- ({ out: format = 'json', parser } = format);
1278
- }
1279
- if (format.includes('/')) {
1280
- format = format.split('/').pop().split('-').pop();
1281
- }
1282
- headers || (headers = {});
1283
- switch (format = format.trim().toLowerCase()) {
1284
- case 'yaml':
1285
- headers['accept'] = 'application/yaml, application/x-yaml, text/yaml, text/x-yaml';
1286
- break;
1287
- case 'json5':
1288
- headers['accept'] = 'application/json5, application/json, text/javascript';
1289
- break;
1290
- case 'xml':
1291
- headers['accept'] = 'application/xml, text/xml';
1292
- break;
1293
- case 'toml':
1294
- headers['accept'] = 'application/toml';
1295
- break;
1296
- default:
1297
- headers['accept'] = 'application/json, text/javascript';
1298
- format = 'json';
1299
- break;
1300
- }
1301
- headers['accept'] += ', text/plain';
1302
- options.encoding = (0, types_1.getEncoding)(encoding);
1303
- options.outFormat = { out: format, parser };
1304
- }
1305
- if (typeof uri !== 'string') {
1306
- url = uri;
1307
- uri = url.toString();
1308
- }
1309
- if (!host) {
1310
- ({ host, url } = this.opts(url || uri));
1311
- options.host = host;
1312
- options.url = url;
1313
- }
1314
- else if (!url) {
1315
- url = new URL(uri);
1316
- options.url = url;
1317
- }
1318
- const checkEncoding = (response, statusCode, contentEncoding = '') => {
1319
- switch (statusCode) {
1320
- case 206 /* HTTP_STATUS.PARTIAL_CONTENT */:
1321
- request.emit('error', new Error('[ABORT] Partial content'));
1322
- case 204 /* HTTP_STATUS.NO_CONTENT */:
1323
- return;
1324
- }
1325
- const chunkSize = outStream?.writableHighWaterMark;
1326
- let pipeTo;
1327
- switch (contentEncoding.trim().toLowerCase()) {
1328
- case 'gzip':
1329
- pipeTo = zlib.createGunzip({ chunkSize });
1330
- break;
1331
- case 'br':
1332
- pipeTo = zlib.createBrotliDecompress({ chunkSize });
1333
- break;
1334
- case 'deflate':
1335
- pipeTo = zlib.createInflate({ chunkSize });
1336
- break;
1337
- case 'deflate-raw':
1338
- pipeTo = zlib.createInflateRaw({ chunkSize });
1339
- break;
1340
- }
1341
- if (pipeTo) {
1342
- if (outStream) {
1343
- stream.pipeline(response, pipeTo, outStream, err => err && response.emit('error', err));
1344
- }
1345
- else {
1346
- stream.pipeline(response, pipeTo, err => err && response.emit('error', err));
1347
- }
1348
- return pipeTo;
1349
- }
1350
- };
1351
- const { hostname, origin } = host;
1352
- const pathname = url.pathname + (socketPath ? '' : url.search);
1353
- const proxy = this.proxyOf(uri, host.localhost);
1354
- let request, ca, cert, key, minVersion, baseHeaders = this.headersOf(uri);
1355
- if (getting && this.acceptEncoding && !host.localhost && !baseHeaders?.['accept-encoding']) {
1356
- (_l = (headers || (headers = {})))['accept-encoding'] || (_l['accept-encoding'] = 'gzip, deflate, br');
1357
- }
1358
- if (host.secure) {
1359
- const secure = this[kCerts]?.[0][origin] || (this.host ? TLS.TEXT[origin] : null);
1360
- if (secure) {
1361
- ({ ca, cert, key, version: minVersion } = secure);
1362
- }
1363
- }
1364
- if (!proxy && httpVersion !== 1 && ((httpVersion || host.version) === 2 && this.httpVersion !== 1 || host.secure && this.httpVersion === 2 && host.failed(2, true) === 0)) {
1365
- request = ((_m = this[kSession][0])[origin] || (_m[origin] = http2.connect(origin, { lookup: this.lookupDns(hostname), ca, cert, key, minVersion }))).request({ ...baseHeaders, ...host_1.default.getBasicAuth(url), ...headers, ':path': pathname, ':method': method });
1366
- if (getting) {
1367
- const listenerMap = {};
1368
- const onEvent = request.on.bind(request);
1369
- const onceEvent = request.once.bind(request);
1370
- let connected, emitter;
1371
- request.on('response', response => {
1372
- connected = true;
1373
- const statusCode = response[':status'];
1374
- if (statusCode >= 200 /* HTTP_STATUS.OK */ && statusCode < 300 /* HTTP_STATUS.MULTIPLE_CHOICES */) {
1375
- if (emitter = checkEncoding(request, statusCode, response['content-encoding'])) {
1376
- for (const event in listenerMap) {
1377
- listenerMap[event].forEach(listener => {
1378
- const [name, type] = event.split('-');
1379
- if (name !== 'error') {
1380
- request.removeListener(name, listener);
1381
- }
1382
- emitter[type](name === 'end' ? 'finish' : name, listener);
1383
- });
1384
- }
1385
- }
1386
- else {
1387
- if (outStream) {
1388
- stream.pipeline(request, outStream, err => err && request.emit('error', err));
1389
- }
1390
- if (encoding) {
1391
- request.setEncoding((0, types_1.getEncoding)(encoding));
1392
- }
1393
- }
1394
- if (LOG_HTTP) {
1395
- this[kConnectHttp][1][origin] = (this[kConnectHttp][1][origin] || 0) + 1;
1396
- }
1397
- }
1398
- request.setTimeout(this._config.timeout);
1399
- });
1400
- request.on = function (event, listener) {
1401
- var _l;
1402
- switch (event) {
1403
- case 'data':
1404
- case 'error':
1405
- case 'end':
1406
- if (emitter) {
1407
- emitter.on(event === 'end' ? 'finish' : event, listener);
1408
- break;
1409
- }
1410
- if (!connected) {
1411
- (listenerMap[_l = event + '-on'] || (listenerMap[_l] = [])).push(listener);
1412
- }
1413
- default:
1414
- onEvent(event, listener);
1415
- break;
1416
- }
1417
- return this;
1418
- };
1419
- request.once = function (event, listener) {
1420
- var _l;
1421
- switch (event) {
1422
- case 'data':
1423
- case 'error':
1424
- case 'end':
1425
- if (emitter) {
1426
- emitter.once(event === 'end' ? 'finish' : event, listener);
1427
- break;
1428
- }
1429
- if (!connected) {
1430
- (listenerMap[_l = event + '-once'] || (listenerMap[_l] = [])).push(listener);
1431
- }
1432
- default:
1433
- onceEvent(event, listener);
1434
- break;
1435
- }
1436
- return this;
1437
- };
1438
- }
1439
- options.httpVersion = 2;
1440
- }
1441
- else {
1442
- let agent;
1443
- if (!socketPath) {
1444
- if (proxy) {
1445
- const pkg = host.secure ? 'https-proxy-agent' : 'http-proxy-agent';
1446
- try {
1447
- const { protocol, hostname: proxyname, port, username, password, href } = proxy.host;
1448
- keepAlive ?? (keepAlive = proxy.keepAlive || false);
1449
- agentTimeout ?? (agentTimeout = proxy.agentTimeout);
1450
- agent = require(pkg)(keepAlive || agentTimeout > 0 ? { protocol, hostname: proxyname, port, username, password, keepAlive, timeout: agentTimeout } : href);
1451
- const proxyHeaders = this[kHeaders] && getBaseHeaders(href, this[kHeaders]) || getBaseHeaders(href, HTTP.HEADERS);
1452
- if (proxyHeaders) {
1453
- baseHeaders = { ...baseHeaders, ...proxyHeaders };
1454
- }
1455
- }
1456
- catch (err) {
1457
- this.checkPackage(err, pkg, "Unknown" /* ERR_MESSAGE.UNKNOWN */);
1458
- }
1459
- }
1460
- else if (keepAlive === false) {
1461
- agent = new (host.secure ? https.Agent : http.Agent)({ keepAlive: false });
1462
- }
1463
- else if (keepAlive === true || agentTimeout > 0) {
1464
- agent = new (host.secure ? https.Agent : http.Agent)({ keepAlive: true, timeout: agentTimeout });
1465
- }
1466
- else if (agentTimeout !== 0) {
1467
- keepAlive = this.keepAlive || false;
1468
- agentTimeout ?? (agentTimeout = this.agentTimeout);
1469
- if (keepAlive || agentTimeout > 0) {
1470
- agent = new (host.secure ? https.Agent : http.Agent)({ keepAlive, timeout: agentTimeout });
1471
- }
1472
- }
1473
- }
1474
- const basicAuth = host_1.default.getBasicAuth(url);
1475
- if (baseHeaders || basicAuth) {
1476
- headers = { ...baseHeaders, ...basicAuth, ...headers };
1477
- }
1478
- request = (host.secure ? https : http).request(socketPath ? { socketPath, path: pathname } : {
1479
- protocol: host.protocol,
1480
- hostname,
1481
- port: host.port,
1482
- path: pathname,
1483
- method,
1484
- ca,
1485
- cert,
1486
- key,
1487
- minVersion,
1488
- headers,
1489
- lookup: this.lookupDns(hostname),
1490
- agent
1491
- }, response => {
1492
- const statusCode = response.statusCode;
1493
- if ((getting || posting) && statusCode >= 200 /* HTTP_STATUS.OK */ && statusCode < 300 /* HTTP_STATUS.MULTIPLE_CHOICES */) {
1494
- let source = checkEncoding(response, statusCode, response.headers['content-encoding']);
1495
- if (source) {
1496
- source.once('finish', () => request.emit('end'));
1497
- }
1498
- else {
1499
- if (encoding) {
1500
- response.setEncoding((0, types_1.getEncoding)(encoding));
1501
- }
1502
- if (outStream) {
1503
- stream.pipeline(response, outStream, err => {
1504
- if (!err) {
1505
- request.emit('end');
1506
- }
1507
- else {
1508
- request.emit('error', err);
1509
- }
1510
- });
1511
- }
1512
- else {
1513
- response.once('end', () => request.emit('end'));
1514
- }
1515
- source = response;
1516
- }
1517
- response
1518
- .on('close', () => request.emit('close'))
1519
- .on('error', err => request.emit('error', err))
1520
- .once('readable', () => request.emit('readable'));
1521
- source.on('data', chunk => request.emit('data', chunk));
1522
- if (response !== source) {
1523
- source.on('error', err => request.emit('error', err));
1524
- }
1525
- if (!posting && !host.didAltSvc(1)) {
1526
- host.upgrade(1, response.headers['alt-svc']);
1527
- }
1528
- if (LOG_HTTP) {
1529
- this[kConnectHttp][0][origin] = (this[kConnectHttp][0][origin] || 0) + 1;
1530
- }
1531
- }
1532
- else {
1533
- response
1534
- .on('close', () => request.emit('close'))
1535
- .on('error', err => request.emit('error', err))
1536
- .once('end', () => request.emit('end'));
1537
- }
1538
- if (this._config.timeout) {
1539
- response.setTimeout(this._config.timeout, () => request.emit('timeout'));
1540
- }
1541
- });
1542
- options.httpVersion = 1;
1543
- }
1544
- if (timeout > 0) {
1545
- request.setTimeout(timeout);
1546
- }
1547
- if ((getting || posting) && SUPPORT_ABORTSIGNAL) {
1548
- const ac = new AbortController();
1549
- this[kDownloading].add(options.outAbort = ac);
1550
- stream.addAbortSignal(ac.signal, request);
1551
- this.signal.addEventListener('abort', () => ac.abort(), { once: true });
1552
- }
1553
- if (posting) {
1554
- if ((0, types_1.isString)(postData) || Buffer.isBuffer(postData)) {
1555
- request.write(postData);
1556
- }
1557
- else if (postData instanceof stream.Stream) {
1558
- postData.pipe(request);
1559
- }
1560
- }
1561
- request.end();
1562
- return request;
1563
- }
1564
- head(uri, options) {
1565
- const out = this.opts(uri, options);
1566
- out.method = 'HEAD';
1567
- out.httpVersion = 1;
1568
- return this.open(out.url, out);
1569
- }
1570
- async post(uri, data, contentType, options) {
1571
- let parts;
1572
- if (Array.isArray(contentType)) {
1573
- parts = contentType;
1574
- contentType = undefined;
1575
- }
1576
- else {
1577
- if ((0, types_1.isPlainObject)(contentType)) {
1578
- options = contentType;
1579
- contentType = undefined;
1580
- }
1581
- if (Array.isArray(data) && (!contentType || contentType === "multipart/form-data" /* MIME.MULTIPART */)) {
1582
- parts = data;
1583
- data = undefined;
1584
- }
1585
- }
1586
- let dataEncoding;
1587
- if ((0, types_1.isPlainObject)(options)) {
1588
- let formData;
1589
- ({ formData, dataEncoding } = options);
1590
- if (formData) {
1591
- (parts || (parts = [])).push(...Array.isArray(formData) ? formData : [formData]);
1592
- }
1593
- else {
1594
- contentType || (contentType = options.contentType);
1595
- }
1596
- }
1597
- else {
1598
- options = {};
1599
- }
1600
- const headers = options.headers || (options.headers = {});
1601
- for (const attr in headers) {
1602
- switch (attr.toLowerCase()) {
1603
- case 'content-type':
1604
- case 'content-length':
1605
- delete headers[attr];
1606
- break;
1607
- }
1608
- }
1609
- if (parts || contentType === "multipart/form-data" /* MIME.MULTIPART */ || contentType === 'form-data') {
1610
- let valid;
1611
- if ((0, types_1.isArray)(parts)) {
1612
- const write = combined.create();
1613
- const boundary = (0, types_1.generateUUID)().replace(/-/g, '');
1614
- contentType = "multipart/form-data" /* MIME.MULTIPART */ + `; boundary="${boundary}"`;
1615
- let contentLength = 0;
1616
- const createPart = (name, filename, type) => {
1617
- const form = ["--" /* FORM_DATA.BOUNDARY_HASH */ + boundary, `Content-Disposition: form-data; name="${escapeQuote(name)}"` + (filename ? `; filename="${escapeQuote(filename)}"` : ''), "\r\n" /* FORM_DATA.CRLF */];
1618
- if (type) {
1619
- form.splice(2, 0, 'Content-Type: ' + type);
1620
- }
1621
- return form.join("\r\n" /* FORM_DATA.CRLF */);
1622
- };
1623
- const addValue = (name, value) => {
1624
- if (value !== undefined) {
1625
- const disposition = createPart(name) + module_1.default.asString(value) + "\r\n" /* FORM_DATA.CRLF */;
1626
- write.append(disposition);
1627
- contentLength += Buffer.byteLength(disposition);
1628
- }
1629
- };
1630
- const escapeQuote = (value) => value.replace(/[\\"]/g, capture => '\\' + capture);
1631
- if ((0, types_1.isPlainObject)(data)) {
1632
- for (const name in data) {
1633
- addValue(name, data[name]);
1634
- }
1635
- }
1636
- for (let { name, data: target, value, contentType: type, filename } of parts) {
1637
- if ((0, types_1.isString)(name)) {
1638
- if (target) {
1639
- try {
1640
- if (typeof target === 'string') {
1641
- filename || (filename = path.basename(target));
1642
- type || (type = module_1.default.lookupMime(filename));
1643
- target = fs.readFileSync(target);
1644
- }
1645
- else if (target instanceof stream.Readable) {
1646
- const chunks = [];
1647
- for await (const chunk of target) {
1648
- chunks.push(chunk);
1649
- }
1650
- target = Buffer.concat(chunks);
1651
- }
1652
- if (!Buffer.isBuffer(target)) {
1653
- throw (0, types_1.errorMessage)('File', "Unknown" /* ERR_MESSAGE.UNKNOWN */, "multipart/form-data" /* MIME.MULTIPART */);
1654
- }
1655
- if (!type || !filename) {
1656
- const result = await module_1.default.resolveMime(target);
1657
- let ext;
1658
- if (result) {
1659
- type || (type = result.mime);
1660
- ext = result.ext;
1661
- }
1662
- else if (type) {
1663
- ext = module_1.default.lookupMime(type, true);
1664
- }
1665
- if (ext && !filename) {
1666
- filename = (0, types_1.generateUUID)() + '.' + ext;
1667
- }
1668
- }
1669
- const disposition = createPart(name, filename, type || "application/octet-stream" /* MIME.OCTET_STREAM */);
1670
- write.append(disposition);
1671
- write.append(target);
1672
- write.append("\r\n" /* FORM_DATA.CRLF */);
1673
- contentLength += Buffer.byteLength(disposition) + target.length + 2 /* FORM_DATA.CRLF_LENGTH */;
1674
- valid = true;
1675
- }
1676
- catch (err) {
1677
- return Promise.reject(err);
1678
- }
1679
- }
1680
- else {
1681
- addValue(name, value);
1682
- }
1683
- }
1684
- }
1685
- if (valid) {
1686
- write.append("--" /* FORM_DATA.BOUNDARY_HASH */ + boundary + "--" /* FORM_DATA.BOUNDARY_HASH */ + "\r\n" /* FORM_DATA.CRLF */);
1687
- headers['content-length'] = (contentLength + 38 /* FORM_DATA.BOUNDARY_LENGTH */).toString();
1688
- data = write;
1689
- }
1690
- }
1691
- if (!valid) {
1692
- return Promise.reject((0, types_1.errorValue)('No files were detected', "multipart/form-data" /* MIME.MULTIPART */));
1693
- }
1694
- }
1695
- else {
1696
- if (contentType && !contentType.includes('/')) {
1697
- contentType = 'application/' + contentType.trim();
1698
- }
1699
- if ((0, types_1.isPlainObject)(data)) {
1700
- if (contentType === "application/x-www-form-urlencoded" /* MIME.URLENCODED */) {
1701
- data = qs.stringify(data);
1702
- }
1703
- else {
1704
- data = JSON.stringify(data);
1705
- contentType || (contentType = "application/json" /* MIME.JSON */);
1706
- }
1707
- }
1708
- else {
1709
- data = module_1.default.asString(data);
1710
- }
1711
- headers['content-length'] = Buffer.byteLength(data, (0, types_1.getEncoding)(dataEncoding)).toString();
1712
- }
1713
- options.method = 'POST';
1714
- options.httpVersion = 1;
1715
- options.postData = data;
1716
- headers['content-type'] = contentType || "text/plain" /* MIME.TEXT */;
1717
- return this.get(uri, options);
1718
- }
1719
- get(uri, options = {}) {
1720
- const opts = (typeof options === 'string' ? { format: options, encoding: 'utf-8' } : options);
1721
- if (this.readExpect === 'string') {
1722
- opts.encoding = (0, types_1.getEncoding)(opts?.encoding);
1723
- }
1724
- return new Promise((resolve, reject) => {
1725
- const { silent = this[kSingleton], pipeTo } = opts;
1726
- const log = LOG_HTTP && LOG_TIMEPROCESS && !silent;
1727
- const startTime = log ? process.hrtime() : 0;
1728
- let retries = 0, redirects = 0, closed, timeout, outStream;
1729
- const throwError = (err, outAbort) => {
1730
- if (!closed) {
1731
- closed = true;
1732
- if (outStream && (0, types_1.isString)(pipeTo)) {
1733
- (0, lib_v4_1.cleanupStream)(outStream, pipeTo);
1734
- }
1735
- reject(typeof err === 'string' ? new Error(err) : err);
1736
- }
1737
- if (timeout) {
1738
- clearTimeout(timeout);
1739
- }
1740
- if (outAbort) {
1741
- this[kDownloading].delete(outAbort);
1742
- }
1743
- };
1744
- const formatStatus = (value, hint) => value + ': ' + (hint || Request.fromStatusCode(value)) + ` (${uri.toString()})`;
1745
- (function downloadUri(href, httpVersion) {
1746
- let outAbort;
1747
- try {
1748
- const request = this.opts(href, opts);
1749
- if (outStream && (0, types_1.isString)(pipeTo)) {
1750
- (0, lib_v4_1.cleanupStream)(outStream, pipeTo);
1751
- }
1752
- if (pipeTo) {
1753
- if ((0, types_1.isString)(pipeTo)) {
1754
- outStream = fs.createWriteStream(pipeTo, { emitClose: false, highWaterMark: request.host.localhost ? 65536 /* CONSTANTS.CHUNK_SIZE_LOCAL */ : 4096 /* CONSTANTS.CHUNK_SIZE */ });
1755
- request.outStream = outStream;
1756
- }
1757
- else {
1758
- request.outStream = pipeTo;
1759
- }
1760
- }
1761
- if (httpVersion) {
1762
- request.httpVersion = httpVersion;
1763
- }
1764
- const client = this.open(href, request);
1765
- const { host, url, encoding, outFormat } = request;
1766
- let buffer, aborted;
1767
- ({ httpVersion, outAbort } = request);
1768
- const isAborted = () => client.destroyed || httpVersion === 2 && client.aborted;
1769
- const isRetry = (value) => (0, util_1.isRetryable)(value) && ++retries <= this._config.retryLimit;
1770
- const isUnsupported = (value) => value === 421 /* HTTP_STATUS.MISDIRECTED_REQUEST */ || value === 505 /* HTTP_STATUS.HTTP_VERSION_NOT_SUPPORTED */;
1771
- const isDowngrade = (err) => err instanceof Error && (err.code === 'ERR_HTTP2_ERROR' || isUnsupported(Math.abs(err.errno)));
1772
- const formatWarning = (message) => LOG_HTTP && !silent && this.formatMessage(1024 /* LOG_TYPE.HTTP */, 'HTTP' + httpVersion, [message, host.origin], url.toString(), { titleBgColor: 'bgGrey', titleColor: 'yellow' });
1773
- const formatNgFlags = (value, statusCode, location) => location ? `Using HTTP 1.1 for URL redirect (${location})` : formatStatus(statusCode, value ? 'NGHTTP2 Error ' + value : '');
1774
- const abortResponse = () => {
1775
- if (closed) {
1776
- return;
1777
- }
1778
- if (timeout) {
1779
- clearTimeout(timeout);
1780
- }
1781
- buffer = null;
1782
- aborted = true;
1783
- if (outAbort) {
1784
- if (!client.aborted) {
1785
- outAbort.abort();
1786
- }
1787
- this[kDownloading].delete(outAbort);
1788
- }
1789
- client.destroy();
1790
- };
1791
- const retryTimeout = () => {
1792
- formatWarning(`Connection timeout (${retries} / ${this._config.retryLimit})`);
1793
- downloadUri.call(this, href);
1794
- };
1795
- const acceptResponse = (headers) => {
1796
- if ('outHeaders' in opts) {
1797
- opts.outHeaders = headers;
1798
- }
1799
- if ('outFilename' in opts) {
1800
- opts.outFilename = (0, util_1.parseHeader)(headers, 'content-disposition');
1801
- }
1802
- const buffering = request.connected?.call(client, headers);
1803
- const pipeline = pipeTo ? !(0, types_1.isString)(pipeTo) : false;
1804
- const enabled = buffering !== false && !pipeline;
1805
- let mibsTime, delayTime;
1806
- if (log || this.readTimeout > 0) {
1807
- client.once('readable', () => {
1808
- if (this.readTimeout > 0) {
1809
- timeout = setTimeout(() => {
1810
- abortResponse();
1811
- throwError((0, types_1.errorValue)("Timeout was exceeded" /* ERR_MESSAGE.TIMEOUT */, href.toString()));
1812
- }, this.readTimeout);
1813
- }
1814
- if (log) {
1815
- if (buffering === false) {
1816
- mibsTime = process.hrtime();
1817
- }
1818
- switch (this.settings?.time_format || LOG_TIMEFORMAT) {
1819
- case 'readable':
1820
- delayTime = process.hrtime(startTime);
1821
- break;
1822
- case 'relative':
1823
- delayTime = Date.now() - this.startTime;
1824
- break;
1825
- }
1826
- }
1827
- });
1828
- }
1829
- if (enabled) {
1830
- client.on('data', (chunk) => {
1831
- if (buffer) {
1832
- if (typeof buffer === 'string') {
1833
- buffer += typeof chunk === 'string' ? chunk : chunk.toString(encoding);
1834
- }
1835
- else if (Array.isArray(buffer)) {
1836
- buffer.push(typeof chunk === 'string' ? Buffer.from(chunk, encoding) : chunk);
1837
- }
1838
- else {
1839
- buffer = Buffer.concat([buffer, typeof chunk === 'string' ? Buffer.from(chunk, encoding) : chunk]);
1840
- }
1841
- }
1842
- else {
1843
- if (log) {
1844
- mibsTime = process.hrtime();
1845
- }
1846
- buffer = typeof chunk === 'string' ? chunk : [chunk];
1847
- }
1848
- });
1849
- }
1850
- client.once('end', () => {
1851
- if (closed || aborted) {
1852
- return;
1853
- }
1854
- if (timeout) {
1855
- clearTimeout(timeout);
1856
- }
1857
- if (outAbort) {
1858
- this[kDownloading].delete(outAbort);
1859
- }
1860
- closed = true;
1861
- let messageUnit, titleBgColor;
1862
- let result;
1863
- if (buffer) {
1864
- if (Array.isArray(buffer)) {
1865
- buffer = Buffer.concat(buffer);
1866
- if (encoding) {
1867
- buffer = buffer.toString(encoding);
1868
- }
1869
- }
1870
- if (mibsTime) {
1871
- const unit = (Buffer.byteLength(buffer, encoding) * 8) / ((0, types_1.convertTime)(process.hrtime(mibsTime)) * 1000 /* TIME.S */);
1872
- if (unit < 1) {
1873
- messageUnit = Math.ceil(unit * 1000 /* TIME.S */) + 'KiB/s';
1874
- }
1875
- else if (unit < 1000 /* TIME.S */) {
1876
- messageUnit = unit.toPrecision(3) + 'MiB/s';
1877
- }
1878
- else {
1879
- messageUnit = (unit / 1000 /* TIME.S */).toPrecision(3) + 'GiB/s';
1880
- }
1881
- }
1882
- if (typeof buffer === 'string') {
1883
- if (buffer[0] === '\uFEFF' && encoding !== 'utf16le') {
1884
- buffer = buffer.substring(1);
1885
- }
1886
- if (outFormat) {
1887
- const { out: format, parser } = outFormat;
1888
- let packageName;
1889
- try {
1890
- switch (format) {
1891
- case 'yaml':
1892
- result = yaml.load(buffer, parser);
1893
- break;
1894
- case 'json5':
1895
- result = require(packageName = 'json5').parse(buffer);
1896
- break;
1897
- case 'xml':
1898
- result = new (require(packageName = 'fast-xml-parser').XMLParser)(parser).parse(buffer);
1899
- break;
1900
- case 'toml':
1901
- result = require(packageName = 'toml').parse(buffer);
1902
- break;
1903
- default:
1904
- result = JSON.parse(buffer);
1905
- break;
1906
- }
1907
- if (!(0, types_1.isObject)(result)) {
1908
- result = null;
1909
- }
1910
- }
1911
- catch (err) {
1912
- if (!silent && !this[kSingleton] && !(packageName && this.checkPackage(err, packageName))) {
1913
- this.writeFail(['Unable to parse URI response', format], err, 1024 /* LOG_TYPE.HTTP */);
1914
- }
1915
- result = null;
1916
- }
1917
- }
1918
- }
1919
- if (result === undefined) {
1920
- result = buffer;
1921
- }
1922
- }
1923
- else if (enabled && this.readExpect === 'always') {
1924
- throwError('No data received');
1925
- return;
1926
- }
1927
- else {
1928
- result = encoding && !pipeline ? '' : null;
1929
- titleBgColor = 'bgBlue';
1930
- }
1931
- resolve(result);
1932
- if (log) {
1933
- this.writeTimeProcess('HTTP' + httpVersion, request.statusMessage || url.toString(), startTime, { type: 1024 /* LOG_TYPE.HTTP */, queue: !!this.host, titleBgColor, messageUnit, messageUnitMinWidth: 9, delayTime, bypassLog: true });
1934
- }
1935
- });
1936
- host.success(httpVersion);
1937
- };
1938
- const redirectResponse = (statusCode, location) => {
1939
- abortResponse();
1940
- if (location) {
1941
- if (++redirects <= this._config.redirectLimit) {
1942
- downloadUri.call(this, Request.fromURL(url, location));
1943
- }
1944
- else {
1945
- throwError(formatStatus(statusCode, 'Exceeded redirect limit'));
1946
- }
1947
- }
1948
- else {
1949
- throwError(formatStatus(statusCode, 'Missing redirect location'));
1950
- }
1951
- };
1952
- const errorResponse = (err) => {
1953
- abortResponse();
1954
- if ((0, util_1.checkRetryable)(err) && ++retries <= this._config.retryLimit) {
1955
- if (isConnectionTimeout(err)) {
1956
- retryTimeout();
1957
- }
1958
- else {
1959
- setTimeout(() => downloadUri.call(this, href), this._config.retryWait);
1960
- }
1961
- }
1962
- else {
1963
- if (err instanceof Error && !err.message.startsWith('[ABORT]')) {
1964
- host.error(httpVersion);
1965
- }
1966
- throwError(err);
1967
- }
1968
- };
1969
- const retryResponse = (statusCode, retryAfter) => {
1970
- abortResponse();
1971
- if (retryAfter && this._config.retryAfter > 0) {
1972
- let offset = +retryAfter || new Date(retryAfter);
1973
- if (offset instanceof Date) {
1974
- offset = Math.max(0, offset.getTime() - Date.now());
1975
- }
1976
- else {
1977
- offset *= 1000;
1978
- }
1979
- if (offset > 0) {
1980
- if (offset <= this._config.retryAfter) {
1981
- formatWarning(`Retry After (${retryAfter})`);
1982
- setTimeout(() => downloadUri.call(this, href), offset);
1983
- }
1984
- else {
1985
- throwError(formatStatus(statusCode));
1986
- }
1987
- return;
1988
- }
1989
- }
1990
- formatWarning(Request.fromStatusCode(statusCode) + ` (${retries} / ${this._config.retryLimit})`);
1991
- if ((0, util_1.isRetryable)(statusCode, true)) {
1992
- process.nextTick(downloadUri.bind(this), href);
1993
- }
1994
- else {
1995
- setTimeout(() => downloadUri.call(this, href), this._config.retryWait);
1996
- }
1997
- };
1998
- if (httpVersion === 2) {
1999
- const retryDownload = (downgrade, message) => {
2000
- if (aborted) {
2001
- return;
2002
- }
2003
- abortResponse();
2004
- if (downgrade) {
2005
- host.failed(2);
2006
- if (host.version > 1) {
2007
- if (!silent) {
2008
- this.formatMessage(1024 /* LOG_TYPE.HTTP */, 'HTTP2', ['Unsupported protocol', host.origin], message, { failed: true });
2009
- }
2010
- host.version = 1;
2011
- }
2012
- }
2013
- downloadUri.call(this, href, 1);
2014
- };
2015
- client
2016
- .on('response', (headers, flags) => {
2017
- if (isAborted()) {
2018
- return;
2019
- }
2020
- const statusCode = headers[':status'];
2021
- if (statusCode < 300 /* HTTP_STATUS.MULTIPLE_CHOICES */) {
2022
- acceptResponse(headers);
2023
- }
2024
- else if (statusCode < 400 /* HTTP_STATUS.BAD_REQUEST */) {
2025
- redirectResponse(statusCode, headers.location);
2026
- }
2027
- else if (statusCode === 401 /* HTTP_STATUS.UNAUTHORIZED */ ||
2028
- statusCode === 402 /* HTTP_STATUS.PAYMENT_REQUIRED */ ||
2029
- statusCode === 403 /* HTTP_STATUS.FORBIDDEN */ ||
2030
- statusCode === 404 /* HTTP_STATUS.NOT_FOUND */ ||
2031
- statusCode === 407 /* HTTP_STATUS.PROXY_AUTHENTICATION_REQUIRED */ ||
2032
- statusCode === 410 /* HTTP_STATUS.GONE */) {
2033
- throwError(formatStatus(statusCode), outAbort);
2034
- }
2035
- else if (isRetry(statusCode)) {
2036
- retryResponse(statusCode, headers['retry-after']);
2037
- }
2038
- else if (isUnsupported(statusCode)) {
2039
- retryDownload(true, formatNgFlags(http2.constants.NGHTTP2_PROTOCOL_ERROR, statusCode));
2040
- }
2041
- else {
2042
- switch (flags) {
2043
- case http2.constants.NGHTTP2_PROTOCOL_ERROR:
2044
- case http2.constants.NGHTTP2_INADEQUATE_SECURITY:
2045
- case http2.constants.NGHTTP2_HTTP_1_1_REQUIRED:
2046
- retryDownload(true, formatNgFlags(flags, statusCode, headers.location));
2047
- break;
2048
- default:
2049
- retryDownload(false, formatStatus(statusCode));
2050
- break;
2051
- }
2052
- }
2053
- })
2054
- .on('unknownProtocol', () => {
2055
- if (!aborted) {
2056
- retryDownload(true, 'Unknown protocol (HTTP/2)');
2057
- }
2058
- })
2059
- .on('aborted', () => {
2060
- aborted = true;
2061
- throwError((0, types_1.createAbortError)(), outAbort);
2062
- })
2063
- .on('error', async (err) => {
2064
- if (aborted) {
2065
- return;
2066
- }
2067
- switch (!isDowngrade(err) && await host.hasProtocol(2)) {
2068
- case 1 /* QUERY_RESULT.OK */:
2069
- errorResponse(err);
2070
- break;
2071
- case 2 /* QUERY_RESULT.TIMEOUT */:
2072
- retryDownload(false, err);
2073
- break;
2074
- default:
2075
- retryDownload(true, err);
2076
- break;
2077
- }
2078
- });
2079
- }
2080
- else {
2081
- client
2082
- .on('response', res => {
2083
- if (isAborted()) {
2084
- return;
2085
- }
2086
- const statusCode = res.statusCode;
2087
- if (statusCode < 300 /* HTTP_STATUS.MULTIPLE_CHOICES */) {
2088
- acceptResponse(res.headers);
2089
- }
2090
- else if (statusCode < 400 /* HTTP_STATUS.BAD_REQUEST */) {
2091
- redirectResponse(statusCode, res.headers.location);
2092
- }
2093
- else if (isRetry(statusCode)) {
2094
- retryResponse(statusCode, res.headers['retry-after']);
2095
- }
2096
- else {
2097
- abortResponse();
2098
- throwError(formatStatus(statusCode));
2099
- }
2100
- })
2101
- .on('abort', () => {
2102
- aborted = true;
2103
- throwError((0, types_1.createAbortError)(), outAbort);
2104
- })
2105
- .on('error', err => {
2106
- if (!aborted) {
2107
- errorResponse(err);
2108
- }
2109
- });
2110
- }
2111
- client.on('timeout', () => {
2112
- if (aborted) {
2113
- return;
2114
- }
2115
- abortResponse();
2116
- if (++retries <= this._config.retryLimit) {
2117
- retryTimeout();
2118
- }
2119
- else {
2120
- throwError(formatStatus(408 /* HTTP_STATUS.REQUEST_TIMEOUT */));
2121
- }
2122
- });
2123
- }
2124
- catch (err) {
2125
- throwError(err, outAbort);
2126
- }
2127
- }).bind(this)(uri);
2128
- });
2129
- }
2130
- reset() {
2131
- this[kPendingDns] = Object.create(null);
2132
- this[kDownloading].clear();
2133
- }
2134
- close() {
2135
- const session = this[kSession];
2136
- session.forEach((protocol, index) => {
2137
- for (const host in protocol) {
2138
- protocol[host].close();
2139
- }
2140
- session[index] = Object.create(null);
2141
- });
2142
- this[kDownloading].clear();
2143
- }
2144
- set agentTimeout(value) {
2145
- if (value > 0) {
2146
- this[kAgentTimeout] = value;
2147
- this.keepAlive ?? (this.keepAlive = true);
2148
- }
2149
- else {
2150
- this[kAgentTimeout] = 0;
2151
- this.keepAlive ?? (this.keepAlive = false);
2152
- }
2153
- }
2154
- get agentTimeout() {
2155
- return this[kAgentTimeout];
2156
- }
2157
- set httpVersion(value) {
2158
- switch (value) {
2159
- case 1:
2160
- case 2:
2161
- this[kHttpVersion] = value;
2162
- break;
2163
- }
2164
- }
2165
- get httpVersion() {
2166
- return this[kHttpVersion];
2167
- }
2168
- set ipVersion(value) {
2169
- switch (value) {
2170
- case 0:
2171
- case 4:
2172
- case 6:
2173
- this[kIpVersion] = value;
2174
- break;
2175
- }
2176
- }
2177
- get ipVersion() {
2178
- return this[kIpVersion];
2179
- }
2180
- get settings() {
2181
- var _l;
2182
- return (_l = this.module).settings || (_l.settings = {});
2183
- }
2184
- }
2185
- _a = kSingleton, _b = kHttpVersion, _c = kHeaders, _d = kCerts, _e = kConnectDns, _f = kPendingDns, _g = kConnectHttp, _h = kDownloading, _j = kHostInfo, _k = kSession;
2186
- exports.default = Request;
1
+ "use strict";
2
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const path = require("path");
5
+ const fs = require("fs");
6
+ const child_process = require("child_process");
7
+ const http = require("http");
8
+ const https = require("https");
9
+ const http2 = require("http2");
10
+ const dns = require("dns");
11
+ const net = require("net");
12
+ const stream = require("stream");
13
+ const zlib = require("zlib");
14
+ const qs = require("querystring");
15
+ const combined = require("combined-stream");
16
+ const yaml = require("js-yaml");
17
+ const which = require("which");
18
+ const lib_v4_1 = require("../module/lib-v4");
19
+ const types_1 = require("../types");
20
+ const module_1 = require("../module");
21
+ const host_1 = require("./http/host");
22
+ const util_1 = require("./util");
23
+ const kSession = Symbol('session');
24
+ const kHttpVersion = Symbol('httpVersion');
25
+ const kIpVersion = Symbol('ipVersion');
26
+ const kAgentTimeout = Symbol('agentTimeout');
27
+ const kHeaders = Symbol('headers');
28
+ const kCerts = Symbol('certs');
29
+ const kDownloading = Symbol('downloading');
30
+ const kSingleton = Symbol('singleton');
31
+ const kHostInfo = Symbol('hostInfo');
32
+ const kConnectDns = Symbol('connectDns');
33
+ const kPendingDns = Symbol('pendingDns');
34
+ const kConnectHttp = Symbol('connectHttp');
35
+ const PLATFORM_WIN32 = process.platform === 'win32';
36
+ const SUPPORT_ABORTSIGNAL = module_1.default.supported(15, 4);
37
+ const HTTP = {
38
+ HOST: {},
39
+ HEADERS: {},
40
+ VERSION: 1,
41
+ PROXY: null
42
+ };
43
+ const TLS = {
44
+ TEXT: {},
45
+ FILE: {}
46
+ };
47
+ const DNS = {
48
+ CACHE: Object.create(null),
49
+ TIMEOUT: [],
50
+ EXPIRES: 0,
51
+ FAMILY: 0
52
+ };
53
+ const ARIA2 = {
54
+ BIN: which.sync(PLATFORM_WIN32 ? 'aria2c.exe' : 'aria2c', { nothrow: true }) || '',
55
+ PID_TIMER: null,
56
+ PID_QUEUE: [],
57
+ UPDATE_STATUS: 0,
58
+ UPDATE_BROADCAST_ONLY: false,
59
+ BT_STOP_TIMEOUT: 60,
60
+ BT_TRACKER_CONNECT_TIMEOUT: 30,
61
+ BT_TRACKER_TIMEOUT: 60,
62
+ MAX_CONCURRENT_DOWNLOADS: 0,
63
+ MAX_CONNECTION_PER_SERVER: 0,
64
+ MIN_SPLIT_SIZE: '',
65
+ DISK_CACHE: null,
66
+ LOWEST_SPEED_LIMIT: null,
67
+ ALWAYS_RESUME: false,
68
+ FILE_ALLOCATION: 'none',
69
+ CONF_PATH: ''
70
+ };
71
+ let KEEP_ALIVE = null;
72
+ let ACCEPT_ENCODING = false;
73
+ let READ_TIMEOUT = 0;
74
+ let AGENT_TIMEOUT = 0;
75
+ let LOG_HTTP = false;
76
+ let LOG_TIMEPROCESS = true;
77
+ let LOG_TIMEFORMAT = 'readable';
78
+ function getBaseHeaders(uri, headers) {
79
+ uri = (0, util_1.trimPath)(uri);
80
+ let result;
81
+ for (const pathname in headers) {
82
+ if (pathname === uri || uri.startsWith(pathname + '/')) {
83
+ (result || (result = [])).push([pathname, headers[pathname]]);
84
+ }
85
+ }
86
+ if (result) {
87
+ if (result.length > 1) {
88
+ result.sort((a, b) => b[0].length - a[0].length);
89
+ }
90
+ return result[0][1];
91
+ }
92
+ }
93
+ function setDnsCache(hostname, value) {
94
+ if (DNS.EXPIRES > 0 && !DNS.CACHE[hostname]) {
95
+ DNS.CACHE[hostname] = value;
96
+ if (DNS.EXPIRES !== Infinity) {
97
+ const timeout = setTimeout(() => {
98
+ const index = DNS.TIMEOUT.findIndex(item => item === timeout);
99
+ if (index !== -1) {
100
+ DNS.TIMEOUT.splice(index, 1);
101
+ }
102
+ DNS.CACHE[hostname] = undefined;
103
+ }, DNS.EXPIRES);
104
+ DNS.TIMEOUT.push(timeout);
105
+ }
106
+ }
107
+ }
108
+ function isConnectionTimeout(err) {
109
+ switch (err instanceof Error && err.code) {
110
+ case 'ETIMEDOUT':
111
+ case 'ECONNRESET':
112
+ return true;
113
+ default:
114
+ return false;
115
+ }
116
+ }
117
+ function setOutgoingHeaders(output, headers) {
118
+ for (const href in headers) {
119
+ output[href] = (0, util_1.normalizeHeaders)(headers[href]);
120
+ }
121
+ }
122
+ function getProxySettings(request, agentTimeout) {
123
+ const proxy = request.proxy;
124
+ if ((0, types_1.isObject)(proxy) && proxy.address && proxy.port) {
125
+ const port = (0, util_1.asInt)(proxy.port);
126
+ const address = (!module_1.default.isURL(proxy.address) ? port === 80 ? 'http://' : 'https://' : '') + proxy.address;
127
+ try {
128
+ let host = new URL(address + ':' + port), include, exclude;
129
+ if ((0, types_1.isString)(proxy.username)) {
130
+ host = new URL(host.protocol + '//' + (0, util_1.getBasicAuth)(proxy.username, proxy.password) + host.host);
131
+ }
132
+ if ((0, types_1.isArray)(proxy.include)) {
133
+ include = proxy.include;
134
+ }
135
+ else if ((0, types_1.isArray)(proxy.exclude)) {
136
+ exclude = proxy.exclude;
137
+ }
138
+ return { host, include, exclude, keepAlive: proxy.keep_alive, agentTimeout };
139
+ }
140
+ catch {
141
+ }
142
+ }
143
+ return null;
144
+ }
145
+ function closeTorrent(pid) {
146
+ if (pid !== undefined) {
147
+ const index = ARIA2.PID_QUEUE.findIndex(value => pid === value[0]);
148
+ if (index !== -1) {
149
+ ARIA2.PID_QUEUE.splice(index, 1);
150
+ }
151
+ }
152
+ }
153
+ function clearDnsLookup() {
154
+ DNS.CACHE = Object.create(null);
155
+ DNS.TIMEOUT.forEach(value => clearTimeout(value));
156
+ DNS.TIMEOUT.length = 0;
157
+ }
158
+ function resetHttpHost(version) {
159
+ switch (version) {
160
+ case 1:
161
+ for (const origin in HTTP.HOST) {
162
+ HTTP.HOST[origin].version = 1;
163
+ }
164
+ break;
165
+ case 2:
166
+ for (const origin in HTTP.HOST) {
167
+ const host = HTTP.HOST[origin];
168
+ if (host.secure && host.version === 1) {
169
+ const failed = host.failed(2, true);
170
+ if (failed === 0 && host.failed(2, true) < 10 /* HOST.MAX_ERROR */ || failed < 3 /* HOST.MAX_FAILED */ && host.success(2, true) > 0) {
171
+ host.version = version;
172
+ }
173
+ }
174
+ }
175
+ break;
176
+ default:
177
+ for (const origin in HTTP.HOST) {
178
+ HTTP.HOST[origin].reset();
179
+ }
180
+ break;
181
+ }
182
+ }
183
+ function validateCerts(certs) {
184
+ const text = {};
185
+ const file = {};
186
+ const checkFile = (values) => {
187
+ for (let pathname of values) {
188
+ if (module_1.default.isPath(pathname = path.resolve(pathname))) {
189
+ return pathname;
190
+ }
191
+ }
192
+ };
193
+ for (let origin in certs) {
194
+ let { ca, cert, key, passphrase, version: minVersion } = certs[origin], file_ca, file_cert, file_key, keyObject;
195
+ try {
196
+ origin = new URL(origin).origin;
197
+ }
198
+ catch {
199
+ continue;
200
+ }
201
+ if (ca) {
202
+ if (!Array.isArray(ca)) {
203
+ ca = [ca];
204
+ }
205
+ file_ca = checkFile(ca);
206
+ ca = ca.map(value => Request.readCACert(value)).filter(value => value);
207
+ if (ca.length === 1) {
208
+ ca = ca[0];
209
+ }
210
+ else if (ca.length === 0) {
211
+ ca = undefined;
212
+ }
213
+ }
214
+ if (cert) {
215
+ if (!Array.isArray(cert)) {
216
+ cert = [cert];
217
+ }
218
+ file_cert = checkFile(cert);
219
+ cert = cert.map(value => Request.readTLSCert(value)).filter(value => value);
220
+ if (cert.length === 1) {
221
+ cert = cert[0];
222
+ }
223
+ else if (cert.length === 0) {
224
+ cert = undefined;
225
+ key = undefined;
226
+ }
227
+ if (key) {
228
+ if (!Array.isArray(key)) {
229
+ key = [key];
230
+ }
231
+ file_key = checkFile(key);
232
+ key = key.map(value => Request.readTLSKey(value)).filter(value => value);
233
+ if (key.length) {
234
+ if (!Array.isArray(passphrase)) {
235
+ passphrase = passphrase ? [passphrase] : [];
236
+ }
237
+ keyObject = key.length > 1 || passphrase.length ? key.map((pem, index) => ({ pem, passphrase: passphrase[index] })) : key[0];
238
+ }
239
+ }
240
+ }
241
+ if (ca || cert) {
242
+ text[origin] = { ca, cert, key: keyObject, version: minVersion };
243
+ }
244
+ if (file_ca || file_cert) {
245
+ file[origin] = { ca: file_ca, cert: file_cert, key: file_key };
246
+ }
247
+ }
248
+ return [text, file];
249
+ }
250
+ class Request extends module_1.default {
251
+ static purgeMemory(percent = 1, limit = 0, parent) {
252
+ if (percent >= 1) {
253
+ resetHttpHost();
254
+ clearDnsLookup();
255
+ }
256
+ else if (percent === 0) {
257
+ clearDnsLookup();
258
+ }
259
+ else {
260
+ resetHttpHost(2);
261
+ }
262
+ return parent ? super.purgeMemory(percent, limit) : Promise.resolve(0);
263
+ }
264
+ static loadSettings(settings, password) {
265
+ if (!this.enabled("process.password" /* KEY_NAME.PROCESS_PASSWORD */) || super.loadSettings({ process: settings.process }, password)) {
266
+ const { request, download } = settings;
267
+ if (download && (0, types_1.isPlainObject)(download.aria2)) {
268
+ let { bin, update_status, max_concurrent_downloads, max_connection_per_server, bt_stop_timeout, bt_tracker_connect_timeout, bt_tracker_timeout, min_split_size, disk_cache, lowest_speed_limit, always_resume, file_allocation, conf_path } = download.aria2;
269
+ const parseSize = (value, zero) => {
270
+ if (zero && (value === '0' || value === 0)) {
271
+ return 0;
272
+ }
273
+ if ((0, types_1.isString)(value) && /^\d+[KM]$/.test(value = value.trim().toUpperCase())) {
274
+ return value;
275
+ }
276
+ };
277
+ if (bin === false) {
278
+ ARIA2.BIN = '';
279
+ }
280
+ else if (bin && this.isPath(bin = path.resolve(bin), true)) {
281
+ ARIA2.BIN = bin;
282
+ }
283
+ if ((0, types_1.isPlainObject)(update_status)) {
284
+ const { interval, broadcast_only } = update_status;
285
+ if (typeof broadcast_only === 'boolean') {
286
+ ARIA2.UPDATE_BROADCAST_ONLY = broadcast_only;
287
+ }
288
+ update_status = interval;
289
+ }
290
+ if ((update_status = (0, util_1.asInt)(update_status)) >= 0) {
291
+ ARIA2.UPDATE_STATUS = update_status;
292
+ }
293
+ if ((max_concurrent_downloads = (0, util_1.asInt)(max_concurrent_downloads)) > 0) {
294
+ ARIA2.MAX_CONCURRENT_DOWNLOADS = max_concurrent_downloads;
295
+ }
296
+ if ((max_connection_per_server = (0, util_1.asInt)(max_connection_per_server)) > 0) {
297
+ ARIA2.MAX_CONNECTION_PER_SERVER = max_connection_per_server;
298
+ }
299
+ if ((bt_stop_timeout = (0, util_1.asInt)(bt_stop_timeout)) >= 0) {
300
+ ARIA2.BT_STOP_TIMEOUT = bt_stop_timeout;
301
+ }
302
+ if ((bt_tracker_connect_timeout = (0, util_1.asInt)(bt_tracker_connect_timeout)) > 0) {
303
+ ARIA2.BT_TRACKER_CONNECT_TIMEOUT = bt_tracker_connect_timeout;
304
+ }
305
+ if ((bt_tracker_timeout = (0, util_1.asInt)(bt_tracker_timeout)) > 0) {
306
+ ARIA2.BT_TRACKER_TIMEOUT = bt_tracker_timeout;
307
+ }
308
+ if (min_split_size = parseSize(min_split_size)) {
309
+ ARIA2.MIN_SPLIT_SIZE = min_split_size;
310
+ }
311
+ if ((disk_cache = parseSize(disk_cache, true)) !== undefined) {
312
+ ARIA2.DISK_CACHE = disk_cache;
313
+ }
314
+ if ((lowest_speed_limit = parseSize(lowest_speed_limit, true)) !== undefined) {
315
+ ARIA2.LOWEST_SPEED_LIMIT = lowest_speed_limit;
316
+ }
317
+ if (always_resume) {
318
+ ARIA2.ALWAYS_RESUME = always_resume;
319
+ }
320
+ if ((0, types_1.isString)(file_allocation)) {
321
+ const value = file_allocation.toLowerCase();
322
+ switch (value) {
323
+ case 'none':
324
+ case 'prealloc':
325
+ case 'trunc':
326
+ case 'falloc':
327
+ ARIA2.FILE_ALLOCATION = value;
328
+ break;
329
+ }
330
+ }
331
+ if (conf_path && this.isPath(conf_path = path.resolve(conf_path))) {
332
+ ARIA2.CONF_PATH = conf_path;
333
+ }
334
+ }
335
+ if ((0, types_1.isPlainObject)(request)) {
336
+ let { read_timeout, agent, use, headers, certs } = request, agent_timeout;
337
+ if ((read_timeout = (0, util_1.fromSeconds)(read_timeout)) >= 0) {
338
+ READ_TIMEOUT = read_timeout;
339
+ }
340
+ if ((0, types_1.isObject)(agent)) {
341
+ let keep_alive;
342
+ ({ keep_alive, timeout: agent_timeout } = agent);
343
+ if ((agent_timeout = (0, util_1.fromSeconds)(agent_timeout)) > 0) {
344
+ AGENT_TIMEOUT = agent_timeout;
345
+ }
346
+ else {
347
+ agent_timeout = undefined;
348
+ }
349
+ if (typeof keep_alive === 'boolean') {
350
+ KEEP_ALIVE = keep_alive;
351
+ }
352
+ else {
353
+ keep_alive = undefined;
354
+ }
355
+ this.defineHttpAgent({ keepAlive: keep_alive, timeout: agent_timeout });
356
+ }
357
+ if ((0, types_1.isObject)(use)) {
358
+ let { http_version, accept_encoding } = use;
359
+ if (typeof accept_encoding === 'boolean') {
360
+ ACCEPT_ENCODING = accept_encoding;
361
+ }
362
+ switch (http_version = (0, util_1.asInt)(http_version)) {
363
+ case 1:
364
+ case 2:
365
+ HTTP.VERSION = http_version;
366
+ break;
367
+ }
368
+ }
369
+ if ((0, types_1.isObject)(headers)) {
370
+ setOutgoingHeaders(HTTP.HEADERS, headers);
371
+ }
372
+ if ((0, types_1.isObject)(certs)) {
373
+ [TLS.TEXT, TLS.FILE] = validateCerts(certs);
374
+ }
375
+ HTTP.PROXY = getProxySettings(request, agent_timeout);
376
+ const time_format = request.settings?.time_format;
377
+ switch (time_format) {
378
+ case 'readable':
379
+ case 'relative':
380
+ case 'none':
381
+ LOG_TIMEFORMAT = time_format;
382
+ break;
383
+ }
384
+ LOG_HTTP = this.hasLogType(1024 /* LOG_TYPE.HTTP */);
385
+ LOG_TIMEPROCESS = this.hasLogType(256 /* LOG_TYPE.TIME_PROCESS */);
386
+ }
387
+ return true;
388
+ }
389
+ return false;
390
+ }
391
+ static readCACert(value, cache) {
392
+ return (0, types_1.isString)(value) ? (this.isCert(value) ? value : this.readText(value, cache)).trim() : '';
393
+ }
394
+ static readTLSCert(value, cache) {
395
+ return this.readCACert(value, cache);
396
+ }
397
+ static readTLSKey(value, cache) {
398
+ return this.readCACert(value, cache);
399
+ }
400
+ static isCert(value) {
401
+ return (0, types_1.isString)(value) && (value = value.trim()) ? value.indexOf('\n') !== -1 && value.startsWith('---') && value.endsWith('---') : false;
402
+ }
403
+ static fromURL(url, value) {
404
+ if (this.isURL(value)) {
405
+ return value;
406
+ }
407
+ const auth = host_1.default.formatBasicAuth(url);
408
+ return url.protocol + '//' + (auth && (auth + '@')) + url.hostname + (url.port ? ':' + url.port : '') + (value[0] !== '/' ? '/' : '') + value;
409
+ }
410
+ static fromStatusCode(value) {
411
+ switch (+value) {
412
+ case 100 /* HTTP_STATUS.CONTINUE */:
413
+ return 'Continue';
414
+ case 101 /* HTTP_STATUS.SWITCHING_PROTOCOL */:
415
+ return 'Switching Protocol';
416
+ case 102 /* HTTP_STATUS.PROCESSING */:
417
+ return 'Processing';
418
+ case 103 /* HTTP_STATUS.EARLY_HINTS */:
419
+ return 'Early Hints';
420
+ case 200 /* HTTP_STATUS.OK */:
421
+ return 'OK';
422
+ case 201 /* HTTP_STATUS.CREATED */:
423
+ return 'Created';
424
+ case 202 /* HTTP_STATUS.ACCEPTED */:
425
+ return 'Accepted';
426
+ case 203 /* HTTP_STATUS.NON_AUTHORITATIVE_INFORMATION */:
427
+ return 'Non-Authoritative Information';
428
+ case 204 /* HTTP_STATUS.NO_CONTENT */:
429
+ return 'No Content';
430
+ case 205 /* HTTP_STATUS.RESET_CONTENT */:
431
+ return 'Reset Content';
432
+ case 206 /* HTTP_STATUS.PARTIAL_CONTENT */:
433
+ return 'Partial Content';
434
+ case 300 /* HTTP_STATUS.MULTIPLE_CHOICES */:
435
+ return 'Multiple Choice';
436
+ case 301 /* HTTP_STATUS.MOVED_PERMANENTLY */:
437
+ return 'Moved Permanently';
438
+ case 302 /* HTTP_STATUS.FOUND */:
439
+ return 'Found';
440
+ case 303 /* HTTP_STATUS.SEE_OTHER */:
441
+ return 'See Other';
442
+ case 304 /* HTTP_STATUS.NOT_MODIFIED */:
443
+ return 'Not Modified';
444
+ case 305 /* HTTP_STATUS.USE_PROXY */:
445
+ return 'Use Proxy';
446
+ case 307 /* HTTP_STATUS.TEMPORARY_REDIRECT */:
447
+ return 'Temporary Redirect';
448
+ case 308 /* HTTP_STATUS.PERMANENT_REDIRECT */:
449
+ return 'Permanent Redirect';
450
+ case 400 /* HTTP_STATUS.BAD_REQUEST */:
451
+ return 'Bad Request';
452
+ case 401 /* HTTP_STATUS.UNAUTHORIZED */:
453
+ return 'Upgrade Required';
454
+ case 402 /* HTTP_STATUS.PAYMENT_REQUIRED */:
455
+ return 'Payment Required';
456
+ case 403 /* HTTP_STATUS.FORBIDDEN */:
457
+ return 'Forbidden';
458
+ case 404 /* HTTP_STATUS.NOT_FOUND */:
459
+ return 'Not Found';
460
+ case 405 /* HTTP_STATUS.METHOD_NOT_ALLOWED */:
461
+ return 'Method Not Allowed';
462
+ case 406 /* HTTP_STATUS.NOT_ACCEPTABLE */:
463
+ return 'Not Acceptable';
464
+ case 407 /* HTTP_STATUS.PROXY_AUTHENTICATION_REQUIRED */:
465
+ return 'Proxy Authentication Required';
466
+ case 408 /* HTTP_STATUS.REQUEST_TIMEOUT */:
467
+ return 'Request Timeout';
468
+ case 409 /* HTTP_STATUS.CONFLICT */:
469
+ return 'Conflict';
470
+ case 410 /* HTTP_STATUS.GONE */:
471
+ return 'Gone';
472
+ case 411 /* HTTP_STATUS.LENGTH_REQUIRED */:
473
+ return 'Length Required';
474
+ case 412 /* HTTP_STATUS.PRECONDITION_FAILED */:
475
+ return 'Precondition Failed';
476
+ case 413 /* HTTP_STATUS.PAYLOAD_TOO_LARGE */:
477
+ return 'Payload Too Large';
478
+ case 414 /* HTTP_STATUS.REQUEST_URI_TOO_LONG */:
479
+ return 'URI Too Long';
480
+ case 415 /* HTTP_STATUS.UNSUPPORTED_MEDIA_TYPE */:
481
+ return 'Unsupported Media Type';
482
+ case 416 /* HTTP_STATUS.RANGE_NOT_SATISFIABLE */:
483
+ return 'Range Not Satisfiable';
484
+ case 417 /* HTTP_STATUS.EXPECTATION_FAILED */:
485
+ return 'Expectation Failed';
486
+ case 421 /* HTTP_STATUS.MISDIRECTED_REQUEST */:
487
+ return 'Misdirected Request';
488
+ case 422 /* HTTP_STATUS.UNPROCESSABLE_ENTITY */:
489
+ return 'Unprocessable Entity';
490
+ case 423 /* HTTP_STATUS.LOCKED */:
491
+ return 'Locked';
492
+ case 424 /* HTTP_STATUS.FAILED_DEPENDENCY */:
493
+ return 'Failed Dependency';
494
+ case 426 /* HTTP_STATUS.UPGRADE_REQUIRED */:
495
+ return 'Upgrade Required';
496
+ case 428 /* HTTP_STATUS.PRECONDITION_REQUIRED */:
497
+ return 'Precondition Required';
498
+ case 429 /* HTTP_STATUS.TOO_MANY_REQUESTS */:
499
+ return 'Too Many Requests';
500
+ case 431 /* HTTP_STATUS.REQUEST_HEADER_FIELDS_TOO_LARGE */:
501
+ return 'Request Header Fields Too Large';
502
+ case 451 /* HTTP_STATUS.UNAVAILABLE_FOR_LEGAL_REASONS */:
503
+ return 'Unavailable For Legal Reasons';
504
+ case 500 /* HTTP_STATUS.INTERNAL_SERVER_ERROR */:
505
+ return 'Internal Server Error';
506
+ case 501 /* HTTP_STATUS.NOT_IMPLEMENTED */:
507
+ return 'Not Implemented';
508
+ case 502 /* HTTP_STATUS.BAD_GATEWAY */:
509
+ return 'Bad Gateway';
510
+ case 503 /* HTTP_STATUS.SERVICE_UNAVAILABLE */:
511
+ return 'Service Unavailable';
512
+ case 504 /* HTTP_STATUS.GATEWAY_TIMEOUT */:
513
+ return 'Gateway Timeout';
514
+ case 505 /* HTTP_STATUS.HTTP_VERSION_NOT_SUPPORTED */:
515
+ return 'HTTP Version Not Supported';
516
+ case 506 /* HTTP_STATUS.VARIANT_ALSO_NEGOTIATES */:
517
+ return 'Variant Also Negotiates';
518
+ case 507 /* HTTP_STATUS.INSUFFICIENT_STORAGE */:
519
+ return 'Insufficient Storage';
520
+ case 508 /* HTTP_STATUS.LOOP_DETECTED */:
521
+ return 'Loop Detected';
522
+ case 510 /* HTTP_STATUS.NOT_EXTENDED */:
523
+ return 'Not Extended';
524
+ case 511 /* HTTP_STATUS.NETWORK_AUTHENTICATION_REQUIRED */:
525
+ return 'Network Authentication Required';
526
+ default:
527
+ return "Unknown" /* ERR_MESSAGE.UNKNOWN */;
528
+ }
529
+ }
530
+ static defineHttpAgent(options) {
531
+ const { keepAlive, timeout = 0 } = options;
532
+ if (options.http instanceof http.Agent) {
533
+ http.globalAgent = options.http;
534
+ }
535
+ else if (timeout > 0) {
536
+ http.globalAgent = new http.Agent({ keepAlive, timeout });
537
+ }
538
+ else if (typeof keepAlive === 'boolean') {
539
+ http.globalAgent = new http.Agent({ keepAlive });
540
+ }
541
+ if (options.https instanceof https.Agent) {
542
+ https.globalAgent = options.https;
543
+ }
544
+ else if (timeout > 0) {
545
+ https.globalAgent = new https.Agent({ keepAlive, timeout });
546
+ }
547
+ else if (typeof keepAlive === 'boolean') {
548
+ https.globalAgent = new https.Agent({ keepAlive });
549
+ }
550
+ }
551
+ static defineDnsLookup({ family, expires, resolve }, reset) {
552
+ if (reset) {
553
+ clearDnsLookup();
554
+ }
555
+ switch (family = (0, util_1.asInt)(family)) {
556
+ case 0:
557
+ case 4:
558
+ case 6:
559
+ DNS.FAMILY = family;
560
+ break;
561
+ }
562
+ if (expires !== undefined) {
563
+ if (typeof expires === 'string') {
564
+ expires = (0, types_1.parseExpires)(expires);
565
+ }
566
+ if (expires >= 0) {
567
+ DNS.EXPIRES = expires !== Infinity ? Math.min(expires, this.MAX_TIMEOUT) : Infinity;
568
+ }
569
+ }
570
+ for (const hostname in resolve) {
571
+ let { address, family: ipv } = resolve[hostname];
572
+ if (address && (ipv = ipv && ((ipv = +ipv) === 4 || ipv === 6) ? ipv : net.isIPv6(address) ? 6 : net.isIPv4(address) ? 4 : 0)) {
573
+ DNS.CACHE[hostname] = [address, ipv];
574
+ }
575
+ }
576
+ }
577
+ static getAria2Path() {
578
+ return ARIA2.BIN;
579
+ }
580
+ constructor(data) {
581
+ super();
582
+ this.startTime = Date.now();
583
+ this.readExpect = 'none';
584
+ this.proxy = null;
585
+ this._moduleName = "request" /* VALUES.MODULE */;
586
+ this._config = {
587
+ timeout: 60000 /* TIME.m */,
588
+ connectTimeout: 20 * 1000 /* TIME.S */,
589
+ redirectLimit: 10,
590
+ retryWait: 1000 /* TIME.S */,
591
+ retryAfter: 30 * 1000 /* TIME.S */,
592
+ retryLimit: 5
593
+ };
594
+ this[_a] = false;
595
+ this[_b] = null;
596
+ this[_c] = null;
597
+ this[_d] = null;
598
+ this[_e] = Object.create(null);
599
+ this[_f] = Object.create(null);
600
+ this[_g] = [{}, {}];
601
+ this[_h] = new Set();
602
+ this[_j] = {};
603
+ this[_k] = [Object.create(null)];
604
+ if ((0, types_1.isPlainObject)(data)) {
605
+ const { headers, read_timeout, agent, use, connect, certs } = data;
606
+ const timeout = (0, util_1.fromSeconds)(data.timeout);
607
+ let value;
608
+ this.readTimeout = (value = (0, util_1.fromSeconds)(read_timeout)) >= 0 ? value : READ_TIMEOUT;
609
+ this.keepAlive = typeof (value = agent?.keep_alive) === 'boolean' ? value : KEEP_ALIVE;
610
+ this.acceptEncoding = typeof (value = use?.accept_encoding) === 'boolean' ? value : ACCEPT_ENCODING;
611
+ switch (value = (0, util_1.asInt)(use?.http_version)) {
612
+ case 1:
613
+ case 2:
614
+ this[kHttpVersion] = value;
615
+ break;
616
+ }
617
+ this[kIpVersion] = (value = (0, util_1.asInt)(data.dns?.family)) && (value === 4 || value === 6) ? value : 0;
618
+ if ((value = (0, util_1.fromSeconds)(agent?.timeout)) >= 0) {
619
+ this[kAgentTimeout] = value;
620
+ }
621
+ else {
622
+ this[kAgentTimeout] = AGENT_TIMEOUT;
623
+ value = undefined;
624
+ }
625
+ const proxy = getProxySettings(data, value);
626
+ if (proxy) {
627
+ this.proxy = proxy;
628
+ }
629
+ if ((0, types_1.isObject)(headers)) {
630
+ setOutgoingHeaders(this[kHeaders] = {}, headers);
631
+ }
632
+ if ((0, types_1.isObject)(certs)) {
633
+ this[kCerts] = validateCerts(certs);
634
+ }
635
+ if ((0, types_1.isObject)(connect)) {
636
+ this.apply({ client: {
637
+ timeout,
638
+ connectTimeout: (0, util_1.fromSeconds)(connect.timeout),
639
+ redirectLimit: (0, util_1.asInt)(connect.redirect_limit),
640
+ retryWait: (0, util_1.fromSeconds)(connect.retry_wait),
641
+ retryAfter: (0, util_1.fromSeconds)(connect.retry_after),
642
+ retryLimit: (0, util_1.asInt)(connect.retry_limit)
643
+ } });
644
+ }
645
+ else if (timeout >= 0) {
646
+ this.apply({ client: { timeout } });
647
+ }
648
+ }
649
+ else {
650
+ data = {};
651
+ this.readTimeout = READ_TIMEOUT;
652
+ this.keepAlive = KEEP_ALIVE;
653
+ this.acceptEncoding = ACCEPT_ENCODING;
654
+ this[kAgentTimeout] = AGENT_TIMEOUT;
655
+ this[kIpVersion] = DNS.FAMILY;
656
+ }
657
+ this.module = data;
658
+ }
659
+ flushLog() {
660
+ if (this[kSingleton]) {
661
+ this._logQueued.length = 0;
662
+ if (LOG_HTTP) {
663
+ this[kConnectHttp] = [{}, {}];
664
+ }
665
+ return;
666
+ }
667
+ if (LOG_HTTP) {
668
+ const log = this._logQueued;
669
+ const output = [];
670
+ let count = 0;
671
+ this[kConnectHttp].forEach((protocol, index) => {
672
+ const title = 'HTTP' + (index + 1);
673
+ for (const origin in protocol) {
674
+ const value = protocol[origin];
675
+ const args = [];
676
+ for (let i = 0; i < log.length; ++i) {
677
+ const item = log[i];
678
+ if (Array.isArray(item[2]) && item[2][0].startsWith(origin)) {
679
+ item[1] = '';
680
+ item[2][0] = item[2][0].substring(origin.length);
681
+ item[4].titleBgColor = undefined;
682
+ item[4].titleJustify = 'right';
683
+ args.push(item);
684
+ log.splice(i--, 1);
685
+ }
686
+ }
687
+ output.push([title, origin, value, args]);
688
+ count = Math.max(count, value);
689
+ }
690
+ });
691
+ if (!this.host?.aborted) {
692
+ output.sort((a, b) => b[2] - a[2]);
693
+ const width = count.toString().length;
694
+ output.forEach(item => {
695
+ const [title, origin, downloads, messages] = item;
696
+ const options = { ...title === 'HTTP1' ? module_1.default.LOG_STYLE_NOTICE : module_1.default.LOG_STYLE_INFO };
697
+ if (messages.length === 1) {
698
+ const message = messages[0];
699
+ message[1] = title;
700
+ message[2] = [origin + message[2][0], message[2][1]];
701
+ message[4] = Object.assign(message[4], options);
702
+ module_1.default.formatMessage(...message);
703
+ }
704
+ else {
705
+ this.formatMessage(1024 /* LOG_TYPE.HTTP */, title, [origin, 'downloads: ' + downloads.toString().padStart(width)], '', options);
706
+ messages.forEach(args => {
707
+ args[4].titleIndent = true;
708
+ module_1.default.formatMessage(...args);
709
+ });
710
+ }
711
+ });
712
+ }
713
+ this[kConnectHttp] = [{}, {}];
714
+ }
715
+ super.flushLog();
716
+ }
717
+ detach(singleton) {
718
+ if (typeof singleton === 'boolean') {
719
+ this[kSingleton] = singleton;
720
+ }
721
+ if (singleton !== false) {
722
+ super.detach();
723
+ }
724
+ }
725
+ abort() {
726
+ this[kDownloading].forEach(item => item.abort());
727
+ this.close();
728
+ if (!this[kSingleton]) {
729
+ super.abort();
730
+ }
731
+ }
732
+ init(config) {
733
+ if (config) {
734
+ const { headers, httpVersion, ipVersion, requestTimeout } = config;
735
+ if ((0, types_1.isObject)(headers)) {
736
+ setOutgoingHeaders(this[kHeaders] || (this[kHeaders] = {}), headers);
737
+ }
738
+ if (httpVersion !== undefined) {
739
+ this.httpVersion = httpVersion;
740
+ }
741
+ if (ipVersion !== undefined) {
742
+ this.ipVersion = ipVersion;
743
+ }
744
+ if (requestTimeout !== undefined) {
745
+ this.readTimeout = (0, util_1.fromSeconds)(requestTimeout);
746
+ }
747
+ }
748
+ return this;
749
+ }
750
+ apply(options) {
751
+ for (const name in options) {
752
+ const value = options[name];
753
+ switch (name) {
754
+ case 'client': {
755
+ const { timeout, connectTimeout, redirectLimit, retryWait, retryAfter, retryLimit } = value;
756
+ if (timeout >= 0) {
757
+ this._config.timeout = timeout;
758
+ }
759
+ if (connectTimeout >= 0) {
760
+ this._config.connectTimeout = connectTimeout;
761
+ }
762
+ if (redirectLimit >= 0) {
763
+ this._config.redirectLimit = redirectLimit;
764
+ }
765
+ if (retryWait >= 0) {
766
+ this._config.retryWait = Math.min(retryWait, 600 * 1000 /* TIME.S */);
767
+ }
768
+ if (retryAfter >= 0) {
769
+ this._config.retryAfter = Math.min(retryAfter, module_1.default.MAX_TIMEOUT);
770
+ }
771
+ if (retryLimit >= 0) {
772
+ this._config.retryLimit = retryLimit;
773
+ }
774
+ break;
775
+ }
776
+ case 'httpVersion':
777
+ case 'ipVersion':
778
+ if (typeof value === 'number') {
779
+ this[name] = value;
780
+ }
781
+ break;
782
+ case 'acceptEncoding':
783
+ case 'keepAlive':
784
+ if (typeof value === 'boolean') {
785
+ this[name] = value;
786
+ }
787
+ break;
788
+ case 'readExpect':
789
+ if ((0, types_1.isString)(value)) {
790
+ this[name] = value;
791
+ }
792
+ break;
793
+ }
794
+ }
795
+ return this;
796
+ }
797
+ addDns(hostname, address, family) {
798
+ if (!this[kConnectDns][hostname]) {
799
+ switch (family) {
800
+ case 'IPv4':
801
+ family = 4;
802
+ break;
803
+ case 'IPv6':
804
+ family = 6;
805
+ break;
806
+ default:
807
+ if (net.isIPv4(address)) {
808
+ family = 4;
809
+ }
810
+ else if (net.isIPv6(address)) {
811
+ family = 6;
812
+ }
813
+ else {
814
+ return;
815
+ }
816
+ break;
817
+ }
818
+ setDnsCache(hostname, this[kConnectDns][hostname] = [address, family]);
819
+ }
820
+ }
821
+ lookupDns(hostname) {
822
+ var _l;
823
+ const resolved = this[kConnectDns][hostname] || DNS.CACHE[hostname];
824
+ if (resolved) {
825
+ return (...args) => args[2](null, ...resolved);
826
+ }
827
+ const pending = (_l = this[kPendingDns])[hostname] || (_l[hostname] = []);
828
+ return (value, options, callback) => {
829
+ if (pending.push(callback) === 1) {
830
+ const configure = (family) => family === 0 ? options : { family, hints: family === 6 ? dns.V4MAPPED : 0 };
831
+ const success = (connected) => {
832
+ setDnsCache(value, this[kConnectDns][value] = connected);
833
+ pending.forEach(cb => cb(null, ...connected));
834
+ pending.length = 0;
835
+ };
836
+ const failed = (err) => {
837
+ pending.forEach(cb => cb(err, '', 0));
838
+ pending.length = 0;
839
+ };
840
+ let ipVersion = this.ipVersion;
841
+ dns.lookup(value, configure(ipVersion), (err, address, family) => {
842
+ if (!err) {
843
+ success([address, family]);
844
+ }
845
+ else {
846
+ switch (err.code) {
847
+ case 'ENOTFOUND':
848
+ case 'EBADNAME':
849
+ case 'ENODATA':
850
+ failed(err);
851
+ return;
852
+ case 'ETIMEOUT':
853
+ case 'ECONNREFUSED':
854
+ case 'ESERVFAIL':
855
+ case 'EFILE':
856
+ ipVersion = 0;
857
+ break;
858
+ default:
859
+ if (ipVersion === 0) {
860
+ failed(err);
861
+ return;
862
+ }
863
+ ipVersion = ipVersion === 4 ? 6 : 4;
864
+ break;
865
+ }
866
+ dns.lookup(value, configure(ipVersion), (err, address, family) => {
867
+ if (!err) {
868
+ success([address, family]);
869
+ }
870
+ else {
871
+ failed(err);
872
+ }
873
+ });
874
+ }
875
+ });
876
+ }
877
+ };
878
+ }
879
+ proxyOf(uri, localhost) {
880
+ const proxy = this.proxy || this.host && HTTP.PROXY;
881
+ if (proxy) {
882
+ const { include, exclude } = proxy;
883
+ if (!include && !exclude && !localhost) {
884
+ return proxy;
885
+ }
886
+ if ((0, types_1.isArray)(include)) {
887
+ return include.some(value => uri.startsWith(value)) ? proxy : undefined;
888
+ }
889
+ if (Array.isArray(exclude) && !exclude.some(value => uri.startsWith(value))) {
890
+ return proxy;
891
+ }
892
+ }
893
+ }
894
+ headersOf(uri) {
895
+ const headers = this[kHeaders];
896
+ return headers && getBaseHeaders(uri, headers) || (this.host ? getBaseHeaders(uri, HTTP.HEADERS) : undefined);
897
+ }
898
+ aria2c(uri, options) {
899
+ if (!ARIA2.BIN) {
900
+ return Promise.reject((0, types_1.errorMessage)("aria2" /* VALUES.ARIA2 */, "Binary not found" /* ERR_MESSAGE.NOTFOUND_BINARY */));
901
+ }
902
+ if (typeof uri === 'string' && module_1.default.isURL(uri)) {
903
+ try {
904
+ uri = new URL(uri);
905
+ }
906
+ catch (err) {
907
+ return Promise.reject(err);
908
+ }
909
+ }
910
+ let pathname, headers, binOpts, silent;
911
+ if (options) {
912
+ if (typeof options === 'string') {
913
+ pathname = options;
914
+ }
915
+ else {
916
+ ({ pathname, headers, binOpts, silent } = options);
917
+ if ((0, types_1.isArray)(binOpts)) {
918
+ let next = false;
919
+ binOpts = binOpts.filter(opt => !((0, types_1.isString)(opt) && /^-[a-z][\S\s]*$/i.test(opt.trim()))).map((opt) => {
920
+ if (next) {
921
+ if (!module_1.default.asString(opt).startsWith('--')) {
922
+ return [];
923
+ }
924
+ next = false;
925
+ }
926
+ switch (typeof opt) {
927
+ case 'string': {
928
+ const value = opt.trim();
929
+ if (value.startsWith('--')) {
930
+ const match = /^(--[a-z]+[a-z0-9-]*)(=)?\s*(.*)$/.exec(value);
931
+ if (match) {
932
+ switch (match[1]) {
933
+ case '--daemon':
934
+ case '--version':
935
+ case '--help':
936
+ break;
937
+ case '--input-file':
938
+ if (!match[2]) {
939
+ next = true;
940
+ }
941
+ break;
942
+ default:
943
+ return match[3] ? [match[1], module_1.default.sanitizeArgs(match[3])] : [match[1]];
944
+ }
945
+ }
946
+ }
947
+ else if (value) {
948
+ return [module_1.default.sanitizeArgs(value)];
949
+ }
950
+ break;
951
+ }
952
+ case 'number':
953
+ case 'boolean':
954
+ return [opt.toString()];
955
+ default:
956
+ if ((0, types_1.isArray)(opt)) {
957
+ return opt.filter(item => (0, types_1.isString)(item)).map((item) => module_1.default.sanitizeArgs(item));
958
+ }
959
+ break;
960
+ }
961
+ return [];
962
+ }).flat();
963
+ }
964
+ }
965
+ }
966
+ if (!(0, types_1.isString)(pathname)) {
967
+ if (this.host) {
968
+ return Promise.reject((0, types_1.errorMessage)("aria2" /* VALUES.ARIA2 */, "Invalid parameters" /* ERR_MESSAGE.PARAMETERS */, 'pathname'));
969
+ }
970
+ pathname = process.cwd();
971
+ }
972
+ if ((this.host || this.hasOwnPermission()) && !this.canWrite(pathname = path.resolve(pathname.trim()))) {
973
+ return Promise.reject((0, types_1.errorMessage)("aria2" /* VALUES.ARIA2 */, "Unsupported access" /* ERR_MESSAGE.UNSUPPORTED_ACCESS */, pathname));
974
+ }
975
+ if (!module_1.default.createDir(pathname)) {
976
+ return Promise.reject((0, types_1.errorMessage)("aria2" /* VALUES.ARIA2 */, "Path is not a directory" /* ERR_MESSAGE.NOT_DIRECTORY */, pathname));
977
+ }
978
+ silent ?? (silent = this[kSingleton]);
979
+ return new Promise((resolve, reject) => {
980
+ let protocol, origin, username, password;
981
+ if (uri instanceof URL) {
982
+ ({ protocol, origin, username, password, href: uri } = uri);
983
+ }
984
+ const escapeQuote = (value) => {
985
+ value = value.replace(/"/g, '\\"');
986
+ return PLATFORM_WIN32 ? value : value.replace(/[ $`]/g, capture => (capture !== ' ' ? '\\' : '') + '\\' + capture);
987
+ };
988
+ const init = [
989
+ `--dir="${escapeQuote(pathname)}"`,
990
+ '--download-result=full',
991
+ '--follow-torrent=mem',
992
+ '--follow-metalink=mem',
993
+ '--seed-time=0',
994
+ '--max-overall-upload-limit=1K',
995
+ '--bt-max-peers=1',
996
+ '--allow-overwrite=true',
997
+ '--dry-run=false',
998
+ '--enable-color=false',
999
+ '--daemon=false',
1000
+ '--stderr=false',
1001
+ '--log=""'
1002
+ ];
1003
+ let args = [];
1004
+ if ((0, types_1.isArray)(binOpts)) {
1005
+ for (let i = 0; i < binOpts.length; ++i) {
1006
+ const leading = binOpts[i] + '=';
1007
+ for (const arg of init) {
1008
+ if (arg.startsWith(leading)) {
1009
+ const items = [];
1010
+ for (let k = i + 1; k < binOpts.length; ++k) {
1011
+ const next = binOpts[k];
1012
+ if (next.startsWith('--')) {
1013
+ break;
1014
+ }
1015
+ items.push(next);
1016
+ }
1017
+ const l = items.length + 1;
1018
+ binOpts.splice(i, l);
1019
+ i += l;
1020
+ break;
1021
+ }
1022
+ }
1023
+ }
1024
+ }
1025
+ else {
1026
+ binOpts = undefined;
1027
+ }
1028
+ const { connectTimeout, timeout, retryWait, retryLimit } = this._config;
1029
+ const opts = [
1030
+ '--log-level=warn',
1031
+ '--bt-stop-timeout=' + ARIA2.BT_STOP_TIMEOUT,
1032
+ '--bt-tracker-connect-timeout=' + ARIA2.BT_TRACKER_CONNECT_TIMEOUT,
1033
+ '--bt-tracker-timeout=' + ARIA2.BT_TRACKER_TIMEOUT,
1034
+ '--file-allocation=' + ARIA2.FILE_ALLOCATION,
1035
+ '--max-tries=' + (retryLimit + 1)
1036
+ ];
1037
+ const ignoreOpt = (...values) => !binOpts?.some(item => values.includes(item));
1038
+ if (ARIA2.MAX_CONCURRENT_DOWNLOADS) {
1039
+ opts.push('--max-concurrent-downloads=' + ARIA2.MAX_CONCURRENT_DOWNLOADS);
1040
+ }
1041
+ if (ARIA2.MAX_CONNECTION_PER_SERVER) {
1042
+ opts.push('--max-connection-per-server=' + ARIA2.MAX_CONNECTION_PER_SERVER);
1043
+ }
1044
+ if (ARIA2.MIN_SPLIT_SIZE) {
1045
+ opts.push('--min-split-size=' + ARIA2.MIN_SPLIT_SIZE);
1046
+ }
1047
+ if (ARIA2.DISK_CACHE !== null) {
1048
+ opts.push('--disk-cache=' + ARIA2.DISK_CACHE);
1049
+ }
1050
+ if (ARIA2.LOWEST_SPEED_LIMIT !== null) {
1051
+ opts.push('--lowest-speed-limit=' + ARIA2.LOWEST_SPEED_LIMIT);
1052
+ }
1053
+ if (ARIA2.CONF_PATH) {
1054
+ opts.push(`--conf-path="${escapeQuote(ARIA2.CONF_PATH)}"`);
1055
+ }
1056
+ if (!ARIA2.ALWAYS_RESUME) {
1057
+ opts.push('--always-resume=false', '--keep-unfinished-download-result=false');
1058
+ }
1059
+ if (connectTimeout > 0) {
1060
+ opts.push('--connect-timeout=' + Math.min(Math.ceil(connectTimeout / 1000), 600));
1061
+ }
1062
+ if (timeout > 0) {
1063
+ opts.push('--timeout=' + Math.min(Math.ceil(timeout / 1000), 600));
1064
+ }
1065
+ if (retryWait > 0) {
1066
+ opts.push('--retry-wait=' + Math.min(Math.ceil(retryWait / 1000), 600));
1067
+ }
1068
+ if (protocol) {
1069
+ if (this.agentTimeout === 0) {
1070
+ opts.push('--enable-http-keep-alive=false');
1071
+ }
1072
+ const baseHeaders = ignoreOpt('--header') && this.headersOf(uri);
1073
+ if (headers || baseHeaders) {
1074
+ if (baseHeaders) {
1075
+ headers = headers ? { ...baseHeaders, ...headers } : baseHeaders;
1076
+ }
1077
+ for (const name in headers) {
1078
+ let items = headers[name];
1079
+ if (!Array.isArray(items)) {
1080
+ items = [items.toString()];
1081
+ }
1082
+ args.push(...items.map(value => `--header="${name}: ${escapeQuote(value)}"`));
1083
+ }
1084
+ }
1085
+ if (origin) {
1086
+ const secure = this[kCerts]?.[1][origin] || (this.host ? TLS.FILE[origin] : null);
1087
+ if (secure) {
1088
+ if (secure.ca && ignoreOpt('--ca-certificate')) {
1089
+ args.push(`--ca-certificate="${escapeQuote(secure.ca)}"`);
1090
+ }
1091
+ if (secure.cert && ignoreOpt('--certificate', '--private-key')) {
1092
+ args.push(`--certificate="${escapeQuote(secure.cert)}"`);
1093
+ if (secure.key) {
1094
+ args.push(`--private-key="${escapeQuote(secure.key)}"`);
1095
+ }
1096
+ }
1097
+ }
1098
+ }
1099
+ switch (protocol = protocol.substring(0, protocol.length - 1)) {
1100
+ case 'ftp':
1101
+ case 'http':
1102
+ case 'https': {
1103
+ const prefix = protocol === 'https' ? 'http' : protocol;
1104
+ if (ignoreOpt(`--${prefix}-user`, `--${prefix}-passwd`)) {
1105
+ if (username) {
1106
+ args.push(`--${prefix}-user="${escapeQuote(decodeURIComponent(username))}"`);
1107
+ }
1108
+ if (password) {
1109
+ args.push(`--${prefix}-passwd="${escapeQuote(decodeURIComponent(password))}"`);
1110
+ }
1111
+ }
1112
+ const proxy = this.proxyOf(uri);
1113
+ if (proxy && ignoreOpt(`--${protocol}-proxy-user`, `--${protocol}-proxy-passwd`)) {
1114
+ ({ origin, username, password } = proxy.host);
1115
+ if (ignoreOpt(`--${protocol}-proxy`)) {
1116
+ args.push(`--${protocol}-proxy="${origin}"`);
1117
+ }
1118
+ if (username) {
1119
+ args.push(`--${protocol}-proxy-user="${escapeQuote(decodeURIComponent(username))}"`);
1120
+ }
1121
+ if (password) {
1122
+ args.push(`--${protocol}-proxy-passwd="${escapeQuote(decodeURIComponent(password))}"`);
1123
+ }
1124
+ }
1125
+ break;
1126
+ }
1127
+ }
1128
+ }
1129
+ if (binOpts) {
1130
+ for (const leading of binOpts) {
1131
+ for (let i = 0; i < opts.length; ++i) {
1132
+ if (opts[i].startsWith(leading)) {
1133
+ opts.splice(i--, i);
1134
+ break;
1135
+ }
1136
+ }
1137
+ }
1138
+ args = binOpts.concat(args);
1139
+ }
1140
+ if (args.length && module_1.default.hasLogType(32768 /* LOG_TYPE.STDOUT */)) {
1141
+ this.formatMessage(32768 /* LOG_TYPE.STDOUT */, 'ARIA2', ARIA2.BIN, args.join(' '), { ...module_1.default.LOG_STYLE_WARN });
1142
+ }
1143
+ opts.push(`"${escapeQuote(uri)}"`);
1144
+ args = args.concat(init, opts);
1145
+ const startTime = Date.now();
1146
+ let out = '', message = '', aborted;
1147
+ const errorResponse = (pid, err) => {
1148
+ aborted = true;
1149
+ closeTorrent(pid);
1150
+ reject(err);
1151
+ };
1152
+ const { pid, stdout, stderr } = child_process.spawn(module_1.default.sanitizeCmd(ARIA2.BIN), args, { cwd: pathname, shell: true, signal: this.signal })
1153
+ .on('exit', code => {
1154
+ closeTorrent(pid);
1155
+ if (aborted) {
1156
+ return;
1157
+ }
1158
+ if (this.aborted) {
1159
+ errorResponse(pid, (0, types_1.createAbortError)());
1160
+ return;
1161
+ }
1162
+ if (!code) {
1163
+ const currentTime = Date.now();
1164
+ const pattern = /\|(OK|ERR|INPR)\s*\|\s*([^|]+)\|\s*(\d+)\|([^\n]+)/g;
1165
+ const result = [];
1166
+ let messageUnit, match;
1167
+ while (match = pattern.exec(out)) {
1168
+ if (match[4].startsWith('[MEMORY]')) {
1169
+ continue;
1170
+ }
1171
+ const file = path.normalize(match[4].trim());
1172
+ switch (match[1]) {
1173
+ case 'OK':
1174
+ if (match[3] === '100') {
1175
+ result.push(file);
1176
+ }
1177
+ messageUnit || (messageUnit = match[2]);
1178
+ break;
1179
+ case 'INPR':
1180
+ if (ARIA2.ALWAYS_RESUME) {
1181
+ break;
1182
+ }
1183
+ case 'ERR':
1184
+ fs.unlink(file, err => err && !silent && !this[kSingleton] && this.writeFail(["Unable to delete file" /* ERR_MESSAGE.DELETE_FILE */, path.basename(file)], err, { type: 32 /* LOG_TYPE.FILE */, fatal: false }));
1185
+ break;
1186
+ }
1187
+ }
1188
+ if (result.length && !silent && LOG_HTTP && LOG_TIMEPROCESS) {
1189
+ this.writeTimeProcess("aria2" /* VALUES.ARIA2 */, uri, startTime, { type: 1024 /* LOG_TYPE.HTTP */, queue: true, messageUnit, messageUnitMinWidth: 9 });
1190
+ }
1191
+ this.addLog(result.length ? types_1.STATUS_TYPE.INFO : types_1.STATUS_TYPE.ERROR, out, currentTime, currentTime - startTime, "aria2" /* VALUES.ARIA2 */, uri);
1192
+ resolve(result);
1193
+ }
1194
+ else {
1195
+ reject((0, types_1.errorValue)(message || "Unknown" /* ERR_MESSAGE.UNKNOWN */, 'Exit status: ' + code));
1196
+ }
1197
+ })
1198
+ .on('error', err => errorResponse(pid, err));
1199
+ stdout.setEncoding('utf-8').on('data', (value) => out += value);
1200
+ stderr.setEncoding('utf-8').on('data', (value) => message += value);
1201
+ if (pid !== undefined && module_1.default.isFile(uri, 'torrent')) {
1202
+ if (!ARIA2.PID_TIMER) {
1203
+ const clearTimer = () => {
1204
+ clearInterval(ARIA2.PID_TIMER);
1205
+ ARIA2.PID_TIMER = null;
1206
+ };
1207
+ ARIA2.PID_TIMER = setInterval(() => {
1208
+ if (ARIA2.PID_QUEUE.length === 0) {
1209
+ clearTimer();
1210
+ return;
1211
+ }
1212
+ for (const item of ARIA2.PID_QUEUE) {
1213
+ try {
1214
+ process.kill(item[0], 0);
1215
+ }
1216
+ catch {
1217
+ closeTorrent(item[0]);
1218
+ }
1219
+ }
1220
+ if (ARIA2.UPDATE_STATUS && !silent) {
1221
+ const item = ARIA2.PID_QUEUE.shift();
1222
+ if (item) {
1223
+ const broadcastId = item[2];
1224
+ if (!ARIA2.UPDATE_BROADCAST_ONLY || broadcastId) {
1225
+ let progressBar;
1226
+ if (item[2]) {
1227
+ progressBar = true;
1228
+ }
1229
+ else {
1230
+ const current = (0, types_1.getLogCurrent)();
1231
+ progressBar = current?.type === 128 /* LOG_TYPE.TIME_ELAPSED */ && current.title === "aria2" /* VALUES.ARIA2 */;
1232
+ }
1233
+ this.formatMessage(128 /* LOG_TYPE.TIME_ELAPSED */, "aria2" /* VALUES.ARIA2 */, ['Downloading...', (0, types_1.formatTime)(startTime, true)], (PLATFORM_WIN32 ? 'taskkill /f /pid' : 'kill') + ` ${item[0]} -> ` + item[1], { ...module_1.default.LOG_STYLE_INFO, progressBar, broadcastId });
1234
+ }
1235
+ ARIA2.PID_QUEUE.push(item);
1236
+ }
1237
+ else {
1238
+ clearTimer();
1239
+ }
1240
+ }
1241
+ }, (ARIA2.UPDATE_STATUS || 30) * 1000 /* TIME.S */);
1242
+ }
1243
+ ARIA2.PID_QUEUE.push([pid, uri, this.broadcastId || undefined]);
1244
+ }
1245
+ });
1246
+ }
1247
+ json(uri, options = {}) {
1248
+ options.format = 'json';
1249
+ return this.get(uri, options);
1250
+ }
1251
+ pipe(uri, to, options = {}) {
1252
+ options.pipeTo = to;
1253
+ return this.get(uri, options);
1254
+ }
1255
+ opts(url, options) {
1256
+ var _l, _m, _o, _p;
1257
+ if (typeof url === 'string') {
1258
+ url = new URL(url);
1259
+ }
1260
+ let host;
1261
+ if (this.host) {
1262
+ host = (_l = HTTP.HOST)[_m = url.origin] || (_l[_m] = new host_1.default(url, HTTP.VERSION));
1263
+ }
1264
+ else {
1265
+ host = (_o = this[kHostInfo])[_p = url.origin] || (_o[_p] = new host_1.default(url, this.httpVersion || 1));
1266
+ }
1267
+ return { ...options, host, url };
1268
+ }
1269
+ open(uri, options) {
1270
+ var _l, _m;
1271
+ let { host, url, httpVersion, method = 'GET', encoding, format, headers, postData, keepAlive, agentTimeout, socketPath, timeout = this._config.connectTimeout, outStream } = options;
1272
+ const getting = method === 'GET';
1273
+ const posting = method === 'POST';
1274
+ if (format) {
1275
+ let parser;
1276
+ if ((0, types_1.isObject)(format)) {
1277
+ ({ out: format = 'json', parser } = format);
1278
+ }
1279
+ if (format.includes('/')) {
1280
+ format = format.split('/').pop().split('-').pop();
1281
+ }
1282
+ headers || (headers = {});
1283
+ switch (format = format.trim().toLowerCase()) {
1284
+ case 'yaml':
1285
+ headers['accept'] = 'application/yaml, application/x-yaml, text/yaml, text/x-yaml';
1286
+ break;
1287
+ case 'json5':
1288
+ headers['accept'] = 'application/json5, application/json, text/javascript';
1289
+ break;
1290
+ case 'xml':
1291
+ headers['accept'] = 'application/xml, text/xml';
1292
+ break;
1293
+ case 'toml':
1294
+ headers['accept'] = 'application/toml';
1295
+ break;
1296
+ default:
1297
+ headers['accept'] = 'application/json, text/javascript';
1298
+ format = 'json';
1299
+ break;
1300
+ }
1301
+ headers['accept'] += ', text/plain';
1302
+ options.encoding = (0, types_1.getEncoding)(encoding);
1303
+ options.outFormat = { out: format, parser };
1304
+ }
1305
+ if (typeof uri !== 'string') {
1306
+ url = uri;
1307
+ uri = url.toString();
1308
+ }
1309
+ if (!host) {
1310
+ ({ host, url } = this.opts(url || uri));
1311
+ options.host = host;
1312
+ options.url = url;
1313
+ }
1314
+ else if (!url) {
1315
+ url = new URL(uri);
1316
+ options.url = url;
1317
+ }
1318
+ const checkEncoding = (response, statusCode, contentEncoding = '') => {
1319
+ switch (statusCode) {
1320
+ case 206 /* HTTP_STATUS.PARTIAL_CONTENT */:
1321
+ request.emit('error', new Error('[ABORT] Partial content'));
1322
+ case 204 /* HTTP_STATUS.NO_CONTENT */:
1323
+ return;
1324
+ }
1325
+ const chunkSize = outStream?.writableHighWaterMark;
1326
+ let pipeTo;
1327
+ switch (contentEncoding.trim().toLowerCase()) {
1328
+ case 'gzip':
1329
+ pipeTo = zlib.createGunzip({ chunkSize });
1330
+ break;
1331
+ case 'br':
1332
+ pipeTo = zlib.createBrotliDecompress({ chunkSize });
1333
+ break;
1334
+ case 'deflate':
1335
+ pipeTo = zlib.createInflate({ chunkSize });
1336
+ break;
1337
+ case 'deflate-raw':
1338
+ pipeTo = zlib.createInflateRaw({ chunkSize });
1339
+ break;
1340
+ }
1341
+ if (pipeTo) {
1342
+ if (outStream) {
1343
+ stream.pipeline(response, pipeTo, outStream, err => err && response.emit('error', err));
1344
+ }
1345
+ else {
1346
+ stream.pipeline(response, pipeTo, err => err && response.emit('error', err));
1347
+ }
1348
+ return pipeTo;
1349
+ }
1350
+ };
1351
+ const { hostname, origin } = host;
1352
+ const pathname = url.pathname + (socketPath ? '' : url.search);
1353
+ const proxy = this.proxyOf(uri, host.localhost);
1354
+ let request, ca, cert, key, minVersion, baseHeaders = this.headersOf(uri);
1355
+ if (getting && this.acceptEncoding && !host.localhost && !baseHeaders?.['accept-encoding']) {
1356
+ (_l = (headers || (headers = {})))['accept-encoding'] || (_l['accept-encoding'] = 'gzip, deflate, br');
1357
+ }
1358
+ if (host.secure) {
1359
+ const secure = this[kCerts]?.[0][origin] || (this.host ? TLS.TEXT[origin] : null);
1360
+ if (secure) {
1361
+ ({ ca, cert, key, version: minVersion } = secure);
1362
+ }
1363
+ }
1364
+ if (!proxy && httpVersion !== 1 && ((httpVersion || host.version) === 2 && this.httpVersion !== 1 || host.secure && this.httpVersion === 2 && host.failed(2, true) === 0)) {
1365
+ request = ((_m = this[kSession][0])[origin] || (_m[origin] = http2.connect(origin, { lookup: this.lookupDns(hostname), ca, cert, key, minVersion }))).request({ ...baseHeaders, ...host_1.default.getBasicAuth(url), ...headers, ':path': pathname, ':method': method });
1366
+ if (getting) {
1367
+ const listenerMap = {};
1368
+ const onEvent = request.on.bind(request);
1369
+ const onceEvent = request.once.bind(request);
1370
+ let connected, emitter;
1371
+ request.on('response', response => {
1372
+ connected = true;
1373
+ const statusCode = response[':status'];
1374
+ if (statusCode >= 200 /* HTTP_STATUS.OK */ && statusCode < 300 /* HTTP_STATUS.MULTIPLE_CHOICES */) {
1375
+ if (emitter = checkEncoding(request, statusCode, response['content-encoding'])) {
1376
+ for (const event in listenerMap) {
1377
+ listenerMap[event].forEach(listener => {
1378
+ const [name, type] = event.split('-');
1379
+ if (name !== 'error') {
1380
+ request.removeListener(name, listener);
1381
+ }
1382
+ emitter[type](name === 'end' ? 'finish' : name, listener);
1383
+ });
1384
+ }
1385
+ }
1386
+ else {
1387
+ if (outStream) {
1388
+ stream.pipeline(request, outStream, err => err && request.emit('error', err));
1389
+ }
1390
+ if (encoding) {
1391
+ request.setEncoding((0, types_1.getEncoding)(encoding));
1392
+ }
1393
+ }
1394
+ if (LOG_HTTP) {
1395
+ this[kConnectHttp][1][origin] = (this[kConnectHttp][1][origin] || 0) + 1;
1396
+ }
1397
+ }
1398
+ request.setTimeout(this._config.timeout);
1399
+ });
1400
+ request.on = function (event, listener) {
1401
+ var _l;
1402
+ switch (event) {
1403
+ case 'data':
1404
+ case 'error':
1405
+ case 'end':
1406
+ if (emitter) {
1407
+ emitter.on(event === 'end' ? 'finish' : event, listener);
1408
+ break;
1409
+ }
1410
+ if (!connected) {
1411
+ (listenerMap[_l = event + '-on'] || (listenerMap[_l] = [])).push(listener);
1412
+ }
1413
+ default:
1414
+ onEvent(event, listener);
1415
+ break;
1416
+ }
1417
+ return this;
1418
+ };
1419
+ request.once = function (event, listener) {
1420
+ var _l;
1421
+ switch (event) {
1422
+ case 'data':
1423
+ case 'error':
1424
+ case 'end':
1425
+ if (emitter) {
1426
+ emitter.once(event === 'end' ? 'finish' : event, listener);
1427
+ break;
1428
+ }
1429
+ if (!connected) {
1430
+ (listenerMap[_l = event + '-once'] || (listenerMap[_l] = [])).push(listener);
1431
+ }
1432
+ default:
1433
+ onceEvent(event, listener);
1434
+ break;
1435
+ }
1436
+ return this;
1437
+ };
1438
+ }
1439
+ options.httpVersion = 2;
1440
+ }
1441
+ else {
1442
+ let agent;
1443
+ if (!socketPath) {
1444
+ if (proxy) {
1445
+ const pkg = host.secure ? 'https-proxy-agent' : 'http-proxy-agent';
1446
+ try {
1447
+ const { protocol, hostname: proxyname, port, username, password, href } = proxy.host;
1448
+ keepAlive ?? (keepAlive = proxy.keepAlive || false);
1449
+ agentTimeout ?? (agentTimeout = proxy.agentTimeout);
1450
+ agent = require(pkg)(keepAlive || agentTimeout > 0 ? { protocol, hostname: proxyname, port, username, password, keepAlive, timeout: agentTimeout } : href);
1451
+ const proxyHeaders = this[kHeaders] && getBaseHeaders(href, this[kHeaders]) || getBaseHeaders(href, HTTP.HEADERS);
1452
+ if (proxyHeaders) {
1453
+ baseHeaders = { ...baseHeaders, ...proxyHeaders };
1454
+ }
1455
+ }
1456
+ catch (err) {
1457
+ this.checkPackage(err, pkg, "Unknown" /* ERR_MESSAGE.UNKNOWN */);
1458
+ }
1459
+ }
1460
+ else if (keepAlive === false) {
1461
+ agent = new (host.secure ? https.Agent : http.Agent)({ keepAlive: false });
1462
+ }
1463
+ else if (keepAlive === true || agentTimeout > 0) {
1464
+ agent = new (host.secure ? https.Agent : http.Agent)({ keepAlive: true, timeout: agentTimeout });
1465
+ }
1466
+ else if (agentTimeout !== 0) {
1467
+ keepAlive = this.keepAlive || false;
1468
+ agentTimeout ?? (agentTimeout = this.agentTimeout);
1469
+ if (keepAlive || agentTimeout > 0) {
1470
+ agent = new (host.secure ? https.Agent : http.Agent)({ keepAlive, timeout: agentTimeout });
1471
+ }
1472
+ }
1473
+ }
1474
+ const basicAuth = host_1.default.getBasicAuth(url);
1475
+ if (baseHeaders || basicAuth) {
1476
+ headers = { ...baseHeaders, ...basicAuth, ...headers };
1477
+ }
1478
+ request = (host.secure ? https : http).request(socketPath ? { socketPath, path: pathname } : {
1479
+ protocol: host.protocol,
1480
+ hostname,
1481
+ port: host.port,
1482
+ path: pathname,
1483
+ method,
1484
+ ca,
1485
+ cert,
1486
+ key,
1487
+ minVersion,
1488
+ headers,
1489
+ lookup: this.lookupDns(hostname),
1490
+ agent
1491
+ }, response => {
1492
+ const statusCode = response.statusCode;
1493
+ if ((getting || posting) && statusCode >= 200 /* HTTP_STATUS.OK */ && statusCode < 300 /* HTTP_STATUS.MULTIPLE_CHOICES */) {
1494
+ let source = checkEncoding(response, statusCode, response.headers['content-encoding']);
1495
+ if (source) {
1496
+ source.once('finish', () => request.emit('end'));
1497
+ }
1498
+ else {
1499
+ if (encoding) {
1500
+ response.setEncoding((0, types_1.getEncoding)(encoding));
1501
+ }
1502
+ if (outStream) {
1503
+ stream.pipeline(response, outStream, err => {
1504
+ if (!err) {
1505
+ request.emit('end');
1506
+ }
1507
+ else {
1508
+ request.emit('error', err);
1509
+ }
1510
+ });
1511
+ }
1512
+ else {
1513
+ response.once('end', () => request.emit('end'));
1514
+ }
1515
+ source = response;
1516
+ }
1517
+ response
1518
+ .on('close', () => request.emit('close'))
1519
+ .on('error', err => request.emit('error', err))
1520
+ .once('readable', () => request.emit('readable'));
1521
+ source.on('data', chunk => request.emit('data', chunk));
1522
+ if (response !== source) {
1523
+ source.on('error', err => request.emit('error', err));
1524
+ }
1525
+ if (!posting && !host.didAltSvc(1)) {
1526
+ host.upgrade(1, response.headers['alt-svc']);
1527
+ }
1528
+ if (LOG_HTTP) {
1529
+ this[kConnectHttp][0][origin] = (this[kConnectHttp][0][origin] || 0) + 1;
1530
+ }
1531
+ }
1532
+ else {
1533
+ response
1534
+ .on('close', () => request.emit('close'))
1535
+ .on('error', err => request.emit('error', err))
1536
+ .once('end', () => request.emit('end'));
1537
+ }
1538
+ if (this._config.timeout) {
1539
+ response.setTimeout(this._config.timeout, () => request.emit('timeout'));
1540
+ }
1541
+ });
1542
+ options.httpVersion = 1;
1543
+ }
1544
+ if (timeout > 0) {
1545
+ request.setTimeout(timeout);
1546
+ }
1547
+ if ((getting || posting) && SUPPORT_ABORTSIGNAL) {
1548
+ const ac = new AbortController();
1549
+ this[kDownloading].add(options.outAbort = ac);
1550
+ stream.addAbortSignal(ac.signal, request);
1551
+ this.signal.addEventListener('abort', () => ac.abort(), { once: true });
1552
+ }
1553
+ if (posting) {
1554
+ if ((0, types_1.isString)(postData) || Buffer.isBuffer(postData)) {
1555
+ request.write(postData);
1556
+ }
1557
+ else if (postData instanceof stream.Stream) {
1558
+ postData.pipe(request);
1559
+ }
1560
+ }
1561
+ request.end();
1562
+ return request;
1563
+ }
1564
+ head(uri, options) {
1565
+ const out = this.opts(uri, options);
1566
+ out.method = 'HEAD';
1567
+ out.httpVersion = 1;
1568
+ return this.open(out.url, out);
1569
+ }
1570
+ async post(uri, data, contentType, options) {
1571
+ let parts;
1572
+ if (Array.isArray(contentType)) {
1573
+ parts = contentType;
1574
+ contentType = undefined;
1575
+ }
1576
+ else {
1577
+ if ((0, types_1.isPlainObject)(contentType)) {
1578
+ options = contentType;
1579
+ contentType = undefined;
1580
+ }
1581
+ if (Array.isArray(data) && (!contentType || contentType === "multipart/form-data" /* MIME.MULTIPART */)) {
1582
+ parts = data;
1583
+ data = undefined;
1584
+ }
1585
+ }
1586
+ let dataEncoding;
1587
+ if ((0, types_1.isPlainObject)(options)) {
1588
+ let formData;
1589
+ ({ formData, dataEncoding } = options);
1590
+ if (formData) {
1591
+ (parts || (parts = [])).push(...Array.isArray(formData) ? formData : [formData]);
1592
+ }
1593
+ else {
1594
+ contentType || (contentType = options.contentType);
1595
+ }
1596
+ }
1597
+ else {
1598
+ options = {};
1599
+ }
1600
+ const headers = options.headers || (options.headers = {});
1601
+ for (const attr in headers) {
1602
+ switch (attr.toLowerCase()) {
1603
+ case 'content-type':
1604
+ case 'content-length':
1605
+ delete headers[attr];
1606
+ break;
1607
+ }
1608
+ }
1609
+ if (parts || contentType === "multipart/form-data" /* MIME.MULTIPART */ || contentType === 'form-data') {
1610
+ let valid;
1611
+ if ((0, types_1.isArray)(parts)) {
1612
+ const write = combined.create();
1613
+ const boundary = (0, types_1.generateUUID)().replace(/-/g, '');
1614
+ contentType = "multipart/form-data" /* MIME.MULTIPART */ + `; boundary="${boundary}"`;
1615
+ let contentLength = 0;
1616
+ const createPart = (name, filename, type) => {
1617
+ const form = ["--" /* FORM_DATA.BOUNDARY_HASH */ + boundary, `Content-Disposition: form-data; name="${escapeQuote(name)}"` + (filename ? `; filename="${escapeQuote(filename)}"` : ''), "\r\n" /* FORM_DATA.CRLF */];
1618
+ if (type) {
1619
+ form.splice(2, 0, 'Content-Type: ' + type);
1620
+ }
1621
+ return form.join("\r\n" /* FORM_DATA.CRLF */);
1622
+ };
1623
+ const addValue = (name, value) => {
1624
+ if (value !== undefined) {
1625
+ const disposition = createPart(name) + module_1.default.asString(value) + "\r\n" /* FORM_DATA.CRLF */;
1626
+ write.append(disposition);
1627
+ contentLength += Buffer.byteLength(disposition);
1628
+ }
1629
+ };
1630
+ const escapeQuote = (value) => value.replace(/[\\"]/g, capture => '\\' + capture);
1631
+ if ((0, types_1.isPlainObject)(data)) {
1632
+ for (const name in data) {
1633
+ addValue(name, data[name]);
1634
+ }
1635
+ }
1636
+ for (let { name, data: target, value, contentType: type, filename } of parts) {
1637
+ if ((0, types_1.isString)(name)) {
1638
+ if (target) {
1639
+ try {
1640
+ if (typeof target === 'string') {
1641
+ filename || (filename = path.basename(target));
1642
+ type || (type = module_1.default.lookupMime(filename));
1643
+ target = fs.readFileSync(target);
1644
+ }
1645
+ else if (target instanceof stream.Readable) {
1646
+ const chunks = [];
1647
+ for await (const chunk of target) {
1648
+ chunks.push(chunk);
1649
+ }
1650
+ target = Buffer.concat(chunks);
1651
+ }
1652
+ if (!Buffer.isBuffer(target)) {
1653
+ throw (0, types_1.errorMessage)('File', "Unknown" /* ERR_MESSAGE.UNKNOWN */, "multipart/form-data" /* MIME.MULTIPART */);
1654
+ }
1655
+ if (!type || !filename) {
1656
+ const result = await module_1.default.resolveMime(target);
1657
+ let ext;
1658
+ if (result) {
1659
+ type || (type = result.mime);
1660
+ ext = result.ext;
1661
+ }
1662
+ else if (type) {
1663
+ ext = module_1.default.lookupMime(type, true);
1664
+ }
1665
+ if (ext && !filename) {
1666
+ filename = (0, types_1.generateUUID)() + '.' + ext;
1667
+ }
1668
+ }
1669
+ const disposition = createPart(name, filename, type || "application/octet-stream" /* MIME.OCTET_STREAM */);
1670
+ write.append(disposition);
1671
+ write.append(target);
1672
+ write.append("\r\n" /* FORM_DATA.CRLF */);
1673
+ contentLength += Buffer.byteLength(disposition) + target.length + 2 /* FORM_DATA.CRLF_LENGTH */;
1674
+ valid = true;
1675
+ }
1676
+ catch (err) {
1677
+ return Promise.reject(err);
1678
+ }
1679
+ }
1680
+ else {
1681
+ addValue(name, value);
1682
+ }
1683
+ }
1684
+ }
1685
+ if (valid) {
1686
+ write.append("--" /* FORM_DATA.BOUNDARY_HASH */ + boundary + "--" /* FORM_DATA.BOUNDARY_HASH */ + "\r\n" /* FORM_DATA.CRLF */);
1687
+ headers['content-length'] = (contentLength + 38 /* FORM_DATA.BOUNDARY_LENGTH */).toString();
1688
+ data = write;
1689
+ }
1690
+ }
1691
+ if (!valid) {
1692
+ return Promise.reject((0, types_1.errorValue)('No files were detected', "multipart/form-data" /* MIME.MULTIPART */));
1693
+ }
1694
+ }
1695
+ else {
1696
+ if (contentType && !contentType.includes('/')) {
1697
+ contentType = 'application/' + contentType.trim();
1698
+ }
1699
+ if ((0, types_1.isPlainObject)(data)) {
1700
+ if (contentType === "application/x-www-form-urlencoded" /* MIME.URLENCODED */) {
1701
+ data = qs.stringify(data);
1702
+ }
1703
+ else {
1704
+ data = JSON.stringify(data);
1705
+ contentType || (contentType = "application/json" /* MIME.JSON */);
1706
+ }
1707
+ }
1708
+ else {
1709
+ data = module_1.default.asString(data);
1710
+ }
1711
+ headers['content-length'] = Buffer.byteLength(data, (0, types_1.getEncoding)(dataEncoding)).toString();
1712
+ }
1713
+ options.method = 'POST';
1714
+ options.httpVersion = 1;
1715
+ options.postData = data;
1716
+ headers['content-type'] = contentType || "text/plain" /* MIME.TEXT */;
1717
+ return this.get(uri, options);
1718
+ }
1719
+ get(uri, options = {}) {
1720
+ const opts = (typeof options === 'string' ? { format: options, encoding: 'utf-8' } : options);
1721
+ if (this.readExpect === 'string') {
1722
+ opts.encoding = (0, types_1.getEncoding)(opts?.encoding);
1723
+ }
1724
+ return new Promise((resolve, reject) => {
1725
+ const { silent = this[kSingleton], pipeTo } = opts;
1726
+ const log = LOG_HTTP && LOG_TIMEPROCESS && !silent;
1727
+ const startTime = log ? process.hrtime() : 0;
1728
+ let retries = 0, redirects = 0, closed, timeout, outStream;
1729
+ const throwError = (err, outAbort) => {
1730
+ if (!closed) {
1731
+ closed = true;
1732
+ if (outStream && (0, types_1.isString)(pipeTo)) {
1733
+ (0, lib_v4_1.cleanupStream)(outStream, pipeTo);
1734
+ }
1735
+ reject(typeof err === 'string' ? new Error(err) : err);
1736
+ }
1737
+ if (timeout) {
1738
+ clearTimeout(timeout);
1739
+ }
1740
+ if (outAbort) {
1741
+ this[kDownloading].delete(outAbort);
1742
+ }
1743
+ };
1744
+ const formatStatus = (value, hint) => value + ': ' + (hint || Request.fromStatusCode(value)) + ` (${uri.toString()})`;
1745
+ (function downloadUri(href, httpVersion) {
1746
+ let outAbort;
1747
+ try {
1748
+ const request = this.opts(href, opts);
1749
+ if (outStream && (0, types_1.isString)(pipeTo)) {
1750
+ (0, lib_v4_1.cleanupStream)(outStream, pipeTo);
1751
+ }
1752
+ if (pipeTo) {
1753
+ if ((0, types_1.isString)(pipeTo)) {
1754
+ outStream = fs.createWriteStream(pipeTo, { emitClose: false, highWaterMark: request.host.localhost ? 65536 /* CONSTANTS.CHUNK_SIZE_LOCAL */ : 4096 /* CONSTANTS.CHUNK_SIZE */ });
1755
+ request.outStream = outStream;
1756
+ }
1757
+ else {
1758
+ request.outStream = pipeTo;
1759
+ }
1760
+ }
1761
+ if (httpVersion) {
1762
+ request.httpVersion = httpVersion;
1763
+ }
1764
+ const client = this.open(href, request);
1765
+ const { host, url, encoding, outFormat } = request;
1766
+ let buffer, aborted;
1767
+ ({ httpVersion, outAbort } = request);
1768
+ const isAborted = () => client.destroyed || httpVersion === 2 && client.aborted;
1769
+ const isRetry = (value) => (0, util_1.isRetryable)(value) && ++retries <= this._config.retryLimit;
1770
+ const isUnsupported = (value) => value === 421 /* HTTP_STATUS.MISDIRECTED_REQUEST */ || value === 505 /* HTTP_STATUS.HTTP_VERSION_NOT_SUPPORTED */;
1771
+ const isDowngrade = (err) => err instanceof Error && (err.code === 'ERR_HTTP2_ERROR' || isUnsupported(Math.abs(err.errno)));
1772
+ const formatWarning = (message) => LOG_HTTP && !silent && this.formatMessage(1024 /* LOG_TYPE.HTTP */, 'HTTP' + httpVersion, [message, host.origin], url.toString(), { titleBgColor: 'bgGrey', titleColor: 'yellow' });
1773
+ const formatNgFlags = (value, statusCode, location) => location ? `Using HTTP 1.1 for URL redirect (${location})` : formatStatus(statusCode, value ? 'NGHTTP2 Error ' + value : '');
1774
+ const abortResponse = () => {
1775
+ if (closed) {
1776
+ return;
1777
+ }
1778
+ if (timeout) {
1779
+ clearTimeout(timeout);
1780
+ }
1781
+ buffer = null;
1782
+ aborted = true;
1783
+ if (outAbort) {
1784
+ if (!client.aborted) {
1785
+ outAbort.abort();
1786
+ }
1787
+ this[kDownloading].delete(outAbort);
1788
+ }
1789
+ client.destroy();
1790
+ };
1791
+ const retryTimeout = () => {
1792
+ formatWarning(`Connection timeout (${retries} / ${this._config.retryLimit})`);
1793
+ downloadUri.call(this, href);
1794
+ };
1795
+ const acceptResponse = (headers) => {
1796
+ if ('outHeaders' in opts) {
1797
+ opts.outHeaders = headers;
1798
+ }
1799
+ if ('outFilename' in opts) {
1800
+ opts.outFilename = (0, util_1.parseHeader)(headers, 'content-disposition');
1801
+ }
1802
+ const buffering = request.connected?.call(client, headers);
1803
+ const pipeline = pipeTo ? !(0, types_1.isString)(pipeTo) : false;
1804
+ const enabled = buffering !== false && !pipeline;
1805
+ let mibsTime, delayTime;
1806
+ if (log || this.readTimeout > 0) {
1807
+ client.once('readable', () => {
1808
+ if (this.readTimeout > 0) {
1809
+ timeout = setTimeout(() => {
1810
+ abortResponse();
1811
+ throwError((0, types_1.errorValue)("Timeout was exceeded" /* ERR_MESSAGE.TIMEOUT */, href.toString()));
1812
+ }, this.readTimeout);
1813
+ }
1814
+ if (log) {
1815
+ if (buffering === false) {
1816
+ mibsTime = process.hrtime();
1817
+ }
1818
+ switch (this.settings?.time_format || LOG_TIMEFORMAT) {
1819
+ case 'readable':
1820
+ delayTime = process.hrtime(startTime);
1821
+ break;
1822
+ case 'relative':
1823
+ delayTime = Date.now() - this.startTime;
1824
+ break;
1825
+ }
1826
+ }
1827
+ });
1828
+ }
1829
+ if (enabled) {
1830
+ client.on('data', (chunk) => {
1831
+ if (buffer) {
1832
+ if (typeof buffer === 'string') {
1833
+ buffer += typeof chunk === 'string' ? chunk : chunk.toString(encoding);
1834
+ }
1835
+ else if (Array.isArray(buffer)) {
1836
+ buffer.push(typeof chunk === 'string' ? Buffer.from(chunk, encoding) : chunk);
1837
+ }
1838
+ else {
1839
+ buffer = Buffer.concat([buffer, typeof chunk === 'string' ? Buffer.from(chunk, encoding) : chunk]);
1840
+ }
1841
+ }
1842
+ else {
1843
+ if (log) {
1844
+ mibsTime = process.hrtime();
1845
+ }
1846
+ buffer = typeof chunk === 'string' ? chunk : [chunk];
1847
+ }
1848
+ });
1849
+ }
1850
+ client.once('end', () => {
1851
+ if (closed || aborted) {
1852
+ return;
1853
+ }
1854
+ if (timeout) {
1855
+ clearTimeout(timeout);
1856
+ }
1857
+ if (outAbort) {
1858
+ this[kDownloading].delete(outAbort);
1859
+ }
1860
+ closed = true;
1861
+ let messageUnit, titleBgColor;
1862
+ let result;
1863
+ if (buffer) {
1864
+ if (Array.isArray(buffer)) {
1865
+ buffer = Buffer.concat(buffer);
1866
+ if (encoding) {
1867
+ buffer = buffer.toString(encoding);
1868
+ }
1869
+ }
1870
+ if (mibsTime) {
1871
+ const unit = (Buffer.byteLength(buffer, encoding) * 8) / ((0, types_1.convertTime)(process.hrtime(mibsTime)) * 1000 /* TIME.S */);
1872
+ if (unit < 1) {
1873
+ messageUnit = Math.ceil(unit * 1000 /* TIME.S */) + 'KiB/s';
1874
+ }
1875
+ else if (unit < 1000 /* TIME.S */) {
1876
+ messageUnit = unit.toPrecision(3) + 'MiB/s';
1877
+ }
1878
+ else {
1879
+ messageUnit = (unit / 1000 /* TIME.S */).toPrecision(3) + 'GiB/s';
1880
+ }
1881
+ }
1882
+ if (typeof buffer === 'string') {
1883
+ if (buffer[0] === '\uFEFF' && encoding !== 'utf16le') {
1884
+ buffer = buffer.substring(1);
1885
+ }
1886
+ if (outFormat) {
1887
+ const { out: format, parser } = outFormat;
1888
+ let packageName;
1889
+ try {
1890
+ switch (format) {
1891
+ case 'yaml':
1892
+ result = yaml.load(buffer, parser);
1893
+ break;
1894
+ case 'json5':
1895
+ result = require(packageName = 'json5').parse(buffer);
1896
+ break;
1897
+ case 'xml':
1898
+ result = new (require(packageName = 'fast-xml-parser').XMLParser)(parser).parse(buffer);
1899
+ break;
1900
+ case 'toml':
1901
+ result = require(packageName = 'toml').parse(buffer);
1902
+ break;
1903
+ default:
1904
+ result = JSON.parse(buffer);
1905
+ break;
1906
+ }
1907
+ if (!(0, types_1.isObject)(result)) {
1908
+ result = null;
1909
+ }
1910
+ }
1911
+ catch (err) {
1912
+ if (!silent && !this[kSingleton] && !(packageName && this.checkPackage(err, packageName))) {
1913
+ this.writeFail(['Unable to parse URI response', format], err, 1024 /* LOG_TYPE.HTTP */);
1914
+ }
1915
+ result = null;
1916
+ }
1917
+ }
1918
+ }
1919
+ if (result === undefined) {
1920
+ result = buffer;
1921
+ }
1922
+ }
1923
+ else if (enabled && this.readExpect === 'always') {
1924
+ throwError('No data received');
1925
+ return;
1926
+ }
1927
+ else {
1928
+ result = encoding && !pipeline ? '' : null;
1929
+ titleBgColor = 'bgBlue';
1930
+ }
1931
+ resolve(result);
1932
+ if (log) {
1933
+ this.writeTimeProcess('HTTP' + httpVersion, request.statusMessage || url.toString(), startTime, { type: 1024 /* LOG_TYPE.HTTP */, queue: !!this.host, titleBgColor, messageUnit, messageUnitMinWidth: 9, delayTime, bypassLog: true });
1934
+ }
1935
+ });
1936
+ host.success(httpVersion);
1937
+ };
1938
+ const redirectResponse = (statusCode, location) => {
1939
+ abortResponse();
1940
+ if (location) {
1941
+ if (++redirects <= this._config.redirectLimit) {
1942
+ downloadUri.call(this, Request.fromURL(url, location));
1943
+ }
1944
+ else {
1945
+ throwError(formatStatus(statusCode, 'Exceeded redirect limit'));
1946
+ }
1947
+ }
1948
+ else {
1949
+ throwError(formatStatus(statusCode, 'Missing redirect location'));
1950
+ }
1951
+ };
1952
+ const errorResponse = (err) => {
1953
+ abortResponse();
1954
+ if ((0, util_1.checkRetryable)(err) && ++retries <= this._config.retryLimit) {
1955
+ if (isConnectionTimeout(err)) {
1956
+ retryTimeout();
1957
+ }
1958
+ else {
1959
+ setTimeout(() => downloadUri.call(this, href), this._config.retryWait);
1960
+ }
1961
+ }
1962
+ else {
1963
+ if (err instanceof Error && !err.message.startsWith('[ABORT]')) {
1964
+ host.error(httpVersion);
1965
+ }
1966
+ throwError(err);
1967
+ }
1968
+ };
1969
+ const retryResponse = (statusCode, retryAfter) => {
1970
+ abortResponse();
1971
+ if (retryAfter && this._config.retryAfter > 0) {
1972
+ let offset = +retryAfter || new Date(retryAfter);
1973
+ if (offset instanceof Date) {
1974
+ offset = Math.max(0, offset.getTime() - Date.now());
1975
+ }
1976
+ else {
1977
+ offset *= 1000;
1978
+ }
1979
+ if (offset > 0) {
1980
+ if (offset <= this._config.retryAfter) {
1981
+ formatWarning(`Retry After (${retryAfter})`);
1982
+ setTimeout(() => downloadUri.call(this, href), offset);
1983
+ }
1984
+ else {
1985
+ throwError(formatStatus(statusCode));
1986
+ }
1987
+ return;
1988
+ }
1989
+ }
1990
+ formatWarning(Request.fromStatusCode(statusCode) + ` (${retries} / ${this._config.retryLimit})`);
1991
+ if ((0, util_1.isRetryable)(statusCode, true)) {
1992
+ process.nextTick(downloadUri.bind(this), href);
1993
+ }
1994
+ else {
1995
+ setTimeout(() => downloadUri.call(this, href), this._config.retryWait);
1996
+ }
1997
+ };
1998
+ if (httpVersion === 2) {
1999
+ const retryDownload = (downgrade, message) => {
2000
+ if (aborted) {
2001
+ return;
2002
+ }
2003
+ abortResponse();
2004
+ if (downgrade) {
2005
+ host.failed(2);
2006
+ if (host.version > 1) {
2007
+ if (!silent) {
2008
+ this.formatMessage(1024 /* LOG_TYPE.HTTP */, 'HTTP2', ['Unsupported protocol', host.origin], message, { failed: true });
2009
+ }
2010
+ host.version = 1;
2011
+ }
2012
+ }
2013
+ downloadUri.call(this, href, 1);
2014
+ };
2015
+ client
2016
+ .on('response', (headers, flags) => {
2017
+ if (isAborted()) {
2018
+ return;
2019
+ }
2020
+ const statusCode = headers[':status'];
2021
+ if (statusCode < 300 /* HTTP_STATUS.MULTIPLE_CHOICES */) {
2022
+ acceptResponse(headers);
2023
+ }
2024
+ else if (statusCode < 400 /* HTTP_STATUS.BAD_REQUEST */) {
2025
+ redirectResponse(statusCode, headers.location);
2026
+ }
2027
+ else if (statusCode === 401 /* HTTP_STATUS.UNAUTHORIZED */ ||
2028
+ statusCode === 402 /* HTTP_STATUS.PAYMENT_REQUIRED */ ||
2029
+ statusCode === 403 /* HTTP_STATUS.FORBIDDEN */ ||
2030
+ statusCode === 404 /* HTTP_STATUS.NOT_FOUND */ ||
2031
+ statusCode === 407 /* HTTP_STATUS.PROXY_AUTHENTICATION_REQUIRED */ ||
2032
+ statusCode === 410 /* HTTP_STATUS.GONE */) {
2033
+ throwError(formatStatus(statusCode), outAbort);
2034
+ }
2035
+ else if (isRetry(statusCode)) {
2036
+ retryResponse(statusCode, headers['retry-after']);
2037
+ }
2038
+ else if (isUnsupported(statusCode)) {
2039
+ retryDownload(true, formatNgFlags(http2.constants.NGHTTP2_PROTOCOL_ERROR, statusCode));
2040
+ }
2041
+ else {
2042
+ switch (flags) {
2043
+ case http2.constants.NGHTTP2_PROTOCOL_ERROR:
2044
+ case http2.constants.NGHTTP2_INADEQUATE_SECURITY:
2045
+ case http2.constants.NGHTTP2_HTTP_1_1_REQUIRED:
2046
+ retryDownload(true, formatNgFlags(flags, statusCode, headers.location));
2047
+ break;
2048
+ default:
2049
+ retryDownload(false, formatStatus(statusCode));
2050
+ break;
2051
+ }
2052
+ }
2053
+ })
2054
+ .on('unknownProtocol', () => {
2055
+ if (!aborted) {
2056
+ retryDownload(true, 'Unknown protocol (HTTP/2)');
2057
+ }
2058
+ })
2059
+ .on('aborted', () => {
2060
+ aborted = true;
2061
+ throwError((0, types_1.createAbortError)(), outAbort);
2062
+ })
2063
+ .on('error', async (err) => {
2064
+ if (aborted) {
2065
+ return;
2066
+ }
2067
+ switch (!isDowngrade(err) && await host.hasProtocol(2)) {
2068
+ case 1 /* QUERY_RESULT.OK */:
2069
+ errorResponse(err);
2070
+ break;
2071
+ case 2 /* QUERY_RESULT.TIMEOUT */:
2072
+ retryDownload(false, err);
2073
+ break;
2074
+ default:
2075
+ retryDownload(true, err);
2076
+ break;
2077
+ }
2078
+ });
2079
+ }
2080
+ else {
2081
+ client
2082
+ .on('response', res => {
2083
+ if (isAborted()) {
2084
+ return;
2085
+ }
2086
+ const statusCode = res.statusCode;
2087
+ if (statusCode < 300 /* HTTP_STATUS.MULTIPLE_CHOICES */) {
2088
+ acceptResponse(res.headers);
2089
+ }
2090
+ else if (statusCode < 400 /* HTTP_STATUS.BAD_REQUEST */) {
2091
+ redirectResponse(statusCode, res.headers.location);
2092
+ }
2093
+ else if (isRetry(statusCode)) {
2094
+ retryResponse(statusCode, res.headers['retry-after']);
2095
+ }
2096
+ else {
2097
+ abortResponse();
2098
+ throwError(formatStatus(statusCode));
2099
+ }
2100
+ })
2101
+ .on('abort', () => {
2102
+ aborted = true;
2103
+ throwError((0, types_1.createAbortError)(), outAbort);
2104
+ })
2105
+ .on('error', err => {
2106
+ if (!aborted) {
2107
+ errorResponse(err);
2108
+ }
2109
+ });
2110
+ }
2111
+ client.on('timeout', () => {
2112
+ if (aborted) {
2113
+ return;
2114
+ }
2115
+ abortResponse();
2116
+ if (++retries <= this._config.retryLimit) {
2117
+ retryTimeout();
2118
+ }
2119
+ else {
2120
+ throwError(formatStatus(408 /* HTTP_STATUS.REQUEST_TIMEOUT */));
2121
+ }
2122
+ });
2123
+ }
2124
+ catch (err) {
2125
+ throwError(err, outAbort);
2126
+ }
2127
+ }).bind(this)(uri);
2128
+ });
2129
+ }
2130
+ reset() {
2131
+ this[kPendingDns] = Object.create(null);
2132
+ this[kDownloading].clear();
2133
+ }
2134
+ close() {
2135
+ const session = this[kSession];
2136
+ session.forEach((protocol, index) => {
2137
+ for (const host in protocol) {
2138
+ protocol[host].close();
2139
+ }
2140
+ session[index] = Object.create(null);
2141
+ });
2142
+ this[kDownloading].clear();
2143
+ }
2144
+ set agentTimeout(value) {
2145
+ if (value > 0) {
2146
+ this[kAgentTimeout] = value;
2147
+ this.keepAlive ?? (this.keepAlive = true);
2148
+ }
2149
+ else {
2150
+ this[kAgentTimeout] = 0;
2151
+ this.keepAlive ?? (this.keepAlive = false);
2152
+ }
2153
+ }
2154
+ get agentTimeout() {
2155
+ return this[kAgentTimeout];
2156
+ }
2157
+ set httpVersion(value) {
2158
+ switch (value) {
2159
+ case 1:
2160
+ case 2:
2161
+ this[kHttpVersion] = value;
2162
+ break;
2163
+ }
2164
+ }
2165
+ get httpVersion() {
2166
+ return this[kHttpVersion];
2167
+ }
2168
+ set ipVersion(value) {
2169
+ switch (value) {
2170
+ case 0:
2171
+ case 4:
2172
+ case 6:
2173
+ this[kIpVersion] = value;
2174
+ break;
2175
+ }
2176
+ }
2177
+ get ipVersion() {
2178
+ return this[kIpVersion];
2179
+ }
2180
+ get settings() {
2181
+ var _l;
2182
+ return (_l = this.module).settings || (_l.settings = {});
2183
+ }
2184
+ }
2185
+ _a = kSingleton, _b = kHttpVersion, _c = kHeaders, _d = kCerts, _e = kConnectDns, _f = kPendingDns, _g = kConnectHttp, _h = kDownloading, _j = kHostInfo, _k = kSession;
2186
+ exports.default = Request;
2187
2187
 
2188
2188
  if (exports.default) {
2189
2189
  module.exports = exports.default;