@e-mc/request 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js ADDED
@@ -0,0 +1,2191 @@
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
+
2188
+ if (exports.default) {
2189
+ module.exports = exports.default;
2190
+ module.exports.default = exports.default;
2191
+ }