@e-mc/request 0.7.1 → 0.8.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.
Files changed (2) hide show
  1. package/index.js +252 -189
  2. package/package.json +4 -3
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
2
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const path = require("path");
5
5
  const fs = require("fs");
@@ -13,6 +13,7 @@ const stream = require("stream");
13
13
  const zlib = require("zlib");
14
14
  const qs = require("querystring");
15
15
  const combined = require("combined-stream");
16
+ const pm = require("picomatch");
16
17
  const yaml = require("js-yaml");
17
18
  const which = require("which");
18
19
  const lib_v4_1 = require("../module/lib-v4");
@@ -32,6 +33,7 @@ const kHostInfo = Symbol('hostInfo');
32
33
  const kConnectDns = Symbol('connectDns');
33
34
  const kPendingDns = Symbol('pendingDns');
34
35
  const kConnectHttp = Symbol('connectHttp');
36
+ const kHeadersOn = Symbol('headersOn');
35
37
  const PLATFORM_WIN32 = process.platform === 'win32';
36
38
  const SUPPORT_NODEJS20 = module_1.default.supported(20);
37
39
  const SUPPORT_ABORTSIGNAL = module_1.default.supported(15, 4);
@@ -258,7 +260,7 @@ function validateCerts(certs) {
258
260
  return [text, file];
259
261
  }
260
262
  class Request extends module_1.default {
261
- static purgeMemory(percent = 1, limit = 0, parent) {
263
+ static async purgeMemory(percent = 1, limit = 0, parent) {
262
264
  if (percent >= 1) {
263
265
  resetHttpHost();
264
266
  clearDnsLookup();
@@ -269,140 +271,140 @@ class Request extends module_1.default {
269
271
  else {
270
272
  resetHttpHost(2);
271
273
  }
272
- return parent ? super.purgeMemory(percent, limit) : Promise.resolve(0);
274
+ return parent ? super.purgeMemory(percent, limit) : 0;
273
275
  }
274
276
  static loadSettings(settings, password) {
275
- if (!this.enabled("process.password" /* KEY_NAME.PROCESS_PASSWORD */) || super.loadSettings({ process: settings.process }, password)) {
276
- const { request, download } = settings;
277
- if (download && (0, types_1.isPlainObject)(download.aria2)) {
278
- let { bin, exec, 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;
279
- const parseSize = (value, zero) => {
280
- if (zero && (value === '0' || value === 0)) {
281
- return 0;
282
- }
283
- if ((0, types_1.isString)(value) && /^\d+[KM]$/.test(value = value.trim().toUpperCase())) {
284
- return value;
285
- }
286
- };
287
- if (bin === false) {
288
- ARIA2.BIN = '';
289
- }
290
- else if (bin && this.isPath(bin = path.resolve(bin), true)) {
291
- ARIA2.BIN = bin;
292
- }
293
- if ((0, types_1.isPlainObject)(exec)) {
294
- let { uid, gid } = exec;
295
- ARIA2.EXEC_UID = (uid = (0, util_1.asInt)(uid)) >= 0 ? uid : undefined;
296
- ARIA2.EXEC_GID = (gid = (0, util_1.asInt)(gid)) >= 0 ? gid : undefined;
297
- }
298
- if ((0, types_1.isPlainObject)(update_status)) {
299
- const { interval, broadcast_only } = update_status;
300
- if (typeof broadcast_only === 'boolean') {
301
- ARIA2.UPDATE_BROADCAST_ONLY = broadcast_only;
302
- }
303
- update_status = interval;
304
- }
305
- if ((update_status = (0, util_1.asInt)(update_status)) >= 0) {
306
- ARIA2.UPDATE_STATUS = update_status;
307
- }
308
- if ((max_concurrent_downloads = (0, util_1.asInt)(max_concurrent_downloads)) > 0) {
309
- ARIA2.MAX_CONCURRENT_DOWNLOADS = max_concurrent_downloads;
310
- }
311
- if ((max_connection_per_server = (0, util_1.asInt)(max_connection_per_server)) > 0) {
312
- ARIA2.MAX_CONNECTION_PER_SERVER = max_connection_per_server;
313
- }
314
- if ((bt_stop_timeout = (0, util_1.asInt)(bt_stop_timeout)) >= 0) {
315
- ARIA2.BT_STOP_TIMEOUT = bt_stop_timeout;
316
- }
317
- if ((bt_tracker_connect_timeout = (0, util_1.asInt)(bt_tracker_connect_timeout)) > 0) {
318
- ARIA2.BT_TRACKER_CONNECT_TIMEOUT = bt_tracker_connect_timeout;
319
- }
320
- if ((bt_tracker_timeout = (0, util_1.asInt)(bt_tracker_timeout)) > 0) {
321
- ARIA2.BT_TRACKER_TIMEOUT = bt_tracker_timeout;
322
- }
323
- if (min_split_size = parseSize(min_split_size)) {
324
- ARIA2.MIN_SPLIT_SIZE = min_split_size;
325
- }
326
- if ((disk_cache = parseSize(disk_cache, true)) !== undefined) {
327
- ARIA2.DISK_CACHE = disk_cache;
328
- }
329
- if ((lowest_speed_limit = parseSize(lowest_speed_limit, true)) !== undefined) {
330
- ARIA2.LOWEST_SPEED_LIMIT = lowest_speed_limit;
277
+ if (this.enabled("process.password" /* KEY_NAME.PROCESS_PASSWORD */) && !super.loadSettings({ process: settings.process }, password)) {
278
+ return false;
279
+ }
280
+ const { request, download } = settings;
281
+ if (download && (0, types_1.isPlainObject)(download.aria2)) {
282
+ let { bin, exec, 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;
283
+ const parseSize = (value, zero) => {
284
+ if (zero && (value === '0' || value === 0)) {
285
+ return 0;
331
286
  }
332
- if (always_resume) {
333
- ARIA2.ALWAYS_RESUME = always_resume;
287
+ if ((0, types_1.isString)(value) && /^\d+[KM]$/.test(value = value.trim().toUpperCase())) {
288
+ return value;
334
289
  }
335
- if ((0, types_1.isString)(file_allocation)) {
336
- const value = file_allocation.toLowerCase();
337
- switch (value) {
338
- case 'none':
339
- case 'prealloc':
340
- case 'trunc':
341
- case 'falloc':
342
- ARIA2.FILE_ALLOCATION = value;
343
- break;
344
- }
290
+ };
291
+ if (bin === false) {
292
+ ARIA2.BIN = '';
293
+ }
294
+ else if (bin && this.isPath(bin = path.resolve(bin), true)) {
295
+ ARIA2.BIN = bin;
296
+ }
297
+ if ((0, types_1.isPlainObject)(exec)) {
298
+ let { uid, gid } = exec;
299
+ ARIA2.EXEC_UID = (uid = (0, util_1.asInt)(uid)) >= 0 ? uid : undefined;
300
+ ARIA2.EXEC_GID = (gid = (0, util_1.asInt)(gid)) >= 0 ? gid : undefined;
301
+ }
302
+ if ((0, types_1.isPlainObject)(update_status)) {
303
+ const { interval, broadcast_only } = update_status;
304
+ if (typeof broadcast_only === 'boolean') {
305
+ ARIA2.UPDATE_BROADCAST_ONLY = broadcast_only;
345
306
  }
346
- if (conf_path && this.isPath(conf_path = path.resolve(conf_path))) {
347
- ARIA2.CONF_PATH = conf_path;
307
+ update_status = interval;
308
+ }
309
+ if ((update_status = (0, util_1.asInt)(update_status)) >= 0) {
310
+ ARIA2.UPDATE_STATUS = update_status;
311
+ }
312
+ if ((max_concurrent_downloads = (0, util_1.asInt)(max_concurrent_downloads)) > 0) {
313
+ ARIA2.MAX_CONCURRENT_DOWNLOADS = max_concurrent_downloads;
314
+ }
315
+ if ((max_connection_per_server = (0, util_1.asInt)(max_connection_per_server)) > 0) {
316
+ ARIA2.MAX_CONNECTION_PER_SERVER = max_connection_per_server;
317
+ }
318
+ if ((bt_stop_timeout = (0, util_1.asInt)(bt_stop_timeout)) >= 0) {
319
+ ARIA2.BT_STOP_TIMEOUT = bt_stop_timeout;
320
+ }
321
+ if ((bt_tracker_connect_timeout = (0, util_1.asInt)(bt_tracker_connect_timeout)) > 0) {
322
+ ARIA2.BT_TRACKER_CONNECT_TIMEOUT = bt_tracker_connect_timeout;
323
+ }
324
+ if ((bt_tracker_timeout = (0, util_1.asInt)(bt_tracker_timeout)) > 0) {
325
+ ARIA2.BT_TRACKER_TIMEOUT = bt_tracker_timeout;
326
+ }
327
+ if (min_split_size = parseSize(min_split_size)) {
328
+ ARIA2.MIN_SPLIT_SIZE = min_split_size;
329
+ }
330
+ if ((disk_cache = parseSize(disk_cache, true)) !== undefined) {
331
+ ARIA2.DISK_CACHE = disk_cache;
332
+ }
333
+ if ((lowest_speed_limit = parseSize(lowest_speed_limit, true)) !== undefined) {
334
+ ARIA2.LOWEST_SPEED_LIMIT = lowest_speed_limit;
335
+ }
336
+ if (always_resume) {
337
+ ARIA2.ALWAYS_RESUME = always_resume;
338
+ }
339
+ if ((0, types_1.isString)(file_allocation)) {
340
+ const value = file_allocation.toLowerCase();
341
+ switch (value) {
342
+ case 'none':
343
+ case 'prealloc':
344
+ case 'trunc':
345
+ case 'falloc':
346
+ ARIA2.FILE_ALLOCATION = value;
347
+ break;
348
348
  }
349
349
  }
350
- if ((0, types_1.isPlainObject)(request)) {
351
- let { read_timeout, agent, use, headers, certs } = request, agent_timeout;
352
- if ((read_timeout = (0, util_1.fromSeconds)(read_timeout)) >= 0) {
353
- READ_TIMEOUT = read_timeout;
350
+ if (conf_path && this.isPath(conf_path = path.resolve(conf_path))) {
351
+ ARIA2.CONF_PATH = conf_path;
352
+ }
353
+ }
354
+ if ((0, types_1.isPlainObject)(request)) {
355
+ let { read_timeout, agent, use, headers, certs } = request, agent_timeout;
356
+ if ((read_timeout = (0, util_1.fromSeconds)(read_timeout)) >= 0) {
357
+ READ_TIMEOUT = read_timeout;
358
+ }
359
+ if ((0, types_1.isObject)(agent)) {
360
+ let keep_alive;
361
+ ({ keep_alive, timeout: agent_timeout } = agent);
362
+ if ((agent_timeout = (0, util_1.fromSeconds)(agent_timeout)) > 0) {
363
+ AGENT_TIMEOUT = agent_timeout;
354
364
  }
355
- if ((0, types_1.isObject)(agent)) {
356
- let keep_alive;
357
- ({ keep_alive, timeout: agent_timeout } = agent);
358
- if ((agent_timeout = (0, util_1.fromSeconds)(agent_timeout)) > 0) {
359
- AGENT_TIMEOUT = agent_timeout;
360
- }
361
- else {
362
- agent_timeout = undefined;
363
- }
364
- if (typeof keep_alive === 'boolean') {
365
- KEEP_ALIVE = keep_alive;
366
- }
367
- else {
368
- keep_alive = undefined;
369
- }
370
- this.defineHttpAgent({ keepAlive: keep_alive, timeout: agent_timeout });
365
+ else {
366
+ agent_timeout = undefined;
371
367
  }
372
- if ((0, types_1.isObject)(use)) {
373
- let { http_version, accept_encoding } = use;
374
- if (typeof accept_encoding === 'boolean') {
375
- ACCEPT_ENCODING = accept_encoding;
376
- }
377
- switch (http_version = (0, util_1.asInt)(http_version)) {
378
- case 1:
379
- case 2:
380
- HTTP.VERSION = http_version;
381
- break;
382
- }
368
+ if (typeof keep_alive === 'boolean') {
369
+ KEEP_ALIVE = keep_alive;
383
370
  }
384
- if ((0, types_1.isObject)(headers)) {
385
- setOutgoingHeaders(HTTP.HEADERS, headers);
371
+ else {
372
+ keep_alive = undefined;
386
373
  }
387
- if ((0, types_1.isObject)(certs)) {
388
- [TLS.TEXT, TLS.FILE] = validateCerts(certs);
374
+ this.defineHttpAgent({ keepAlive: keep_alive, timeout: agent_timeout });
375
+ }
376
+ if ((0, types_1.isObject)(use)) {
377
+ let { http_version, accept_encoding } = use;
378
+ if (typeof accept_encoding === 'boolean') {
379
+ ACCEPT_ENCODING = accept_encoding;
389
380
  }
390
- HTTP.PROXY = getProxySettings(request, agent_timeout);
391
- const time_format = request.settings?.time_format;
392
- switch (time_format) {
393
- case 'readable':
394
- case 'relative':
395
- case 'none':
396
- LOG_TIMEFORMAT = time_format;
381
+ switch (http_version = (0, util_1.asInt)(http_version)) {
382
+ case 1:
383
+ case 2:
384
+ HTTP.VERSION = http_version;
397
385
  break;
398
386
  }
399
387
  }
400
- LOG_HTTP = this.hasLogType(1024 /* LOG_TYPE.HTTP */);
401
- LOG_TIMEPROCESS = this.hasLogType(256 /* LOG_TYPE.TIME_PROCESS */);
402
- LOG_STDOUT = module_1.default.hasLogType(32768 /* LOG_TYPE.STDOUT */);
403
- return true;
388
+ if ((0, types_1.isObject)(headers)) {
389
+ setOutgoingHeaders(HTTP.HEADERS, headers);
390
+ }
391
+ if ((0, types_1.isObject)(certs)) {
392
+ [TLS.TEXT, TLS.FILE] = validateCerts(certs);
393
+ }
394
+ HTTP.PROXY = getProxySettings(request, agent_timeout);
395
+ const time_format = request.settings?.time_format;
396
+ switch (time_format) {
397
+ case 'readable':
398
+ case 'relative':
399
+ case 'none':
400
+ LOG_TIMEFORMAT = time_format;
401
+ break;
402
+ }
404
403
  }
405
- return false;
404
+ LOG_HTTP = this.hasLogType(1024 /* LOG_TYPE.HTTP */);
405
+ LOG_TIMEPROCESS = this.hasLogType(256 /* LOG_TYPE.TIME_PROCESS */);
406
+ LOG_STDOUT = module_1.default.hasLogType(32768 /* LOG_TYPE.STDOUT */);
407
+ return true;
406
408
  }
407
409
  static readCACert(value, cache) {
408
410
  return (0, types_1.isString)(value) ? (this.isCert(value) ? value : this.readText(value, cache)).trim() : '';
@@ -414,14 +416,14 @@ class Request extends module_1.default {
414
416
  return this.readCACert(value, cache);
415
417
  }
416
418
  static isCert(value) {
417
- return (0, types_1.isString)(value) && (value = value.trim()) ? value.indexOf('\n') !== -1 && value.startsWith('---') && value.endsWith('---') : false;
419
+ return (0, types_1.isString)(value) && (value = value.trim()) ? value.includes('\n') && value.startsWith('---') && value.endsWith('---') : false;
418
420
  }
419
421
  static fromURL(url, value) {
420
422
  if (this.isURL(value)) {
421
423
  return value;
422
424
  }
423
425
  const auth = host_1.default.formatBasicAuth(url);
424
- return url.protocol + '//' + (auth && (auth + '@')) + url.hostname + (url.port ? ':' + url.port : '') + (value[0] !== '/' ? '/' : '') + value;
426
+ return url.protocol + '//' + (auth && (auth + '@')) + url.hostname + (url.port ? ':' + url.port : '') + (value.startsWith('/') ? '' : '/') + value;
425
427
  }
426
428
  static fromStatusCode(value) {
427
429
  if ((value = +value) < 200) {
@@ -616,6 +618,7 @@ class Request extends module_1.default {
616
618
  this.readExpect = 'none';
617
619
  this.proxy = null;
618
620
  this._moduleName = "request" /* VALUES.MODULE */;
621
+ this._threadable = true;
619
622
  this._config = {
620
623
  timeout: 60000 /* TIME.m */,
621
624
  connectTimeout: 20 * 1000 /* TIME.S */,
@@ -634,6 +637,7 @@ class Request extends module_1.default {
634
637
  this[_h] = new Set();
635
638
  this[_j] = {};
636
639
  this[_k] = [Object.create(null)];
640
+ this[_l] = new Map();
637
641
  if ((0, types_1.isPlainObject)(data)) {
638
642
  const { headers, read_timeout, agent, use, connect, certs } = data;
639
643
  const timeout = (0, util_1.fromSeconds)(data.timeout);
@@ -750,11 +754,11 @@ class Request extends module_1.default {
750
754
  super.detach();
751
755
  }
752
756
  }
753
- abort() {
754
- this[kDownloading].forEach(item => item.abort());
757
+ abort(reason) {
758
+ this[kDownloading].forEach(item => item.abort(reason));
755
759
  this.close();
756
760
  if (!this[kSingleton]) {
757
- super.abort();
761
+ super.abort(reason);
758
762
  }
759
763
  }
760
764
  init(config) {
@@ -845,14 +849,14 @@ class Request extends module_1.default {
845
849
  setDnsCache(hostname, this[kConnectDns][hostname] = [{ address, family }]);
846
850
  }
847
851
  lookupDns(hostname) {
848
- var _l;
852
+ var _m;
849
853
  const resolved = this[kConnectDns][hostname] || DNS.CACHE[hostname];
850
854
  if (resolved) {
851
855
  return (...args) => {
852
856
  return SUPPORT_NODEJS20 ? args[2](null, resolved) : args[2](null, resolved[0].address, resolved[0].family);
853
857
  };
854
858
  }
855
- const pending = (_l = this[kPendingDns])[hostname] || (_l[hostname] = []);
859
+ const pending = (_m = this[kPendingDns])[hostname] || (_m[hostname] = []);
856
860
  return (value, options, callback) => {
857
861
  if (pending.push(callback) === 1) {
858
862
  const configure = (family) => family === 0 ? options : { family, hints: family === 6 ? dns.V4MAPPED : 0 };
@@ -875,62 +879,76 @@ class Request extends module_1.default {
875
879
  dns.lookup(value, configure(ipVersion), (err, address, family) => {
876
880
  if (!err) {
877
881
  success(typeof address === 'string' ? [{ address, family }] : address);
882
+ return;
878
883
  }
879
- else {
880
- switch (err.code) {
881
- case 'ENOTFOUND':
882
- case 'EBADNAME':
883
- case 'ENODATA':
884
+ switch (err.code) {
885
+ case 'ENOTFOUND':
886
+ case 'EBADNAME':
887
+ case 'ENODATA':
888
+ failed(err);
889
+ return;
890
+ case 'ETIMEOUT':
891
+ case 'ECONNREFUSED':
892
+ case 'ESERVFAIL':
893
+ case 'EFILE':
894
+ ipVersion = 0;
895
+ break;
896
+ default:
897
+ if (ipVersion === 0) {
884
898
  failed(err);
885
899
  return;
886
- case 'ETIMEOUT':
887
- case 'ECONNREFUSED':
888
- case 'ESERVFAIL':
889
- case 'EFILE':
890
- ipVersion = 0;
891
- break;
892
- default:
893
- if (ipVersion === 0) {
894
- failed(err);
895
- return;
896
- }
897
- ipVersion = ipVersion === 4 ? 6 : 4;
898
- break;
899
- }
900
- dns.lookup(value, configure(ipVersion), (err, address, family) => {
901
- if (!err) {
902
- success(typeof address === 'string' ? [{ address, family }] : address);
903
900
  }
904
- else {
905
- failed(err);
906
- }
907
- });
901
+ ipVersion = ipVersion === 4 ? 6 : 4;
902
+ break;
908
903
  }
904
+ dns.lookup(value, configure(ipVersion), (err, address, family) => {
905
+ if (!err) {
906
+ success(typeof address === 'string' ? [{ address, family }] : address);
907
+ }
908
+ else {
909
+ failed(err);
910
+ }
911
+ });
909
912
  });
910
913
  }
911
914
  };
912
915
  }
913
916
  proxyOf(uri, localhost) {
914
917
  const proxy = this.proxy || this.host && HTTP.PROXY;
915
- if (!proxy) {
916
- return;
917
- }
918
- const { include, exclude } = proxy;
919
- if (!include && !exclude && !localhost) {
920
- return proxy;
921
- }
922
- if ((0, types_1.isArray)(include)) {
923
- return include.some(value => uri.startsWith(value)) ? proxy : undefined;
918
+ if (proxy) {
919
+ const { include, exclude } = proxy;
920
+ if (!include && !exclude && !localhost) {
921
+ return proxy;
922
+ }
923
+ if ((0, types_1.isArray)(include)) {
924
+ return include.some(value => uri.startsWith(value)) ? proxy : undefined;
925
+ }
926
+ if (Array.isArray(exclude) && !exclude.some(value => uri.startsWith(value))) {
927
+ return proxy;
928
+ }
924
929
  }
925
- if (Array.isArray(exclude) && !exclude.some(value => uri.startsWith(value))) {
926
- return proxy;
930
+ }
931
+ headersOn(name, patternUrl = '*', callback) {
932
+ if (typeof patternUrl === 'function') {
933
+ callback = patternUrl;
934
+ patternUrl = '*';
935
+ }
936
+ if ((0, types_1.isString)(patternUrl) && typeof callback === 'function') {
937
+ const on = this[kHeadersOn];
938
+ for (const item of !Array.isArray(name) ? [name] : name) {
939
+ let headers = on.get(item);
940
+ if (!headers) {
941
+ on.set(item, headers = []);
942
+ }
943
+ headers.push([patternUrl, callback]);
944
+ }
927
945
  }
928
946
  }
929
947
  headersOf(uri) {
930
948
  const headers = this[kHeaders];
931
949
  return headers && getBaseHeaders(uri, headers) || (this.host ? getBaseHeaders(uri, HTTP.HEADERS) : undefined);
932
950
  }
933
- aria2c(uri, options) {
951
+ async aria2c(uri, options) {
934
952
  if (!ARIA2.BIN) {
935
953
  return Promise.reject((0, types_1.errorMessage)("aria2" /* VALUES.ARIA2 */, "Binary not found" /* ERR_MESSAGE.NOTFOUND_BINARY */));
936
954
  }
@@ -1284,30 +1302,30 @@ class Request extends module_1.default {
1284
1302
  }
1285
1303
  });
1286
1304
  }
1287
- json(uri, options = {}) {
1305
+ async json(uri, options = {}) {
1288
1306
  options.format = 'json';
1289
1307
  return this.get(uri, options);
1290
1308
  }
1291
- pipe(uri, to, options = {}) {
1309
+ async pipe(uri, to, options = {}) {
1292
1310
  options.pipeTo = to;
1293
1311
  return this.get(uri, options);
1294
1312
  }
1295
1313
  opts(url, options) {
1296
- var _l, _m, _o, _p;
1314
+ var _m, _o, _p, _q;
1297
1315
  if (typeof url === 'string') {
1298
1316
  url = new URL(url);
1299
1317
  }
1300
1318
  let host;
1301
1319
  if (this.host) {
1302
- host = (_l = HTTP.HOST)[_m = url.origin] || (_l[_m] = new host_1.default(url, HTTP.VERSION));
1320
+ host = (_m = HTTP.HOST)[_o = url.origin] || (_m[_o] = new host_1.default(url, HTTP.VERSION));
1303
1321
  }
1304
1322
  else {
1305
- host = (_o = this[kHostInfo])[_p = url.origin] || (_o[_p] = new host_1.default(url, this.httpVersion || 1));
1323
+ host = (_p = this[kHostInfo])[_q = url.origin] || (_p[_q] = new host_1.default(url, this.httpVersion || 1));
1306
1324
  }
1307
1325
  return { ...options, host, url };
1308
1326
  }
1309
1327
  open(uri, options) {
1310
- var _l, _m;
1328
+ var _m, _o;
1311
1329
  let { host, url, httpVersion, method = 'GET', encoding, format, headers, postData, keepAlive, agentTimeout, socketPath, timeout = this._config.connectTimeout, outStream } = options;
1312
1330
  const getting = method === 'GET';
1313
1331
  const posting = method === 'POST';
@@ -1358,7 +1376,7 @@ class Request extends module_1.default {
1358
1376
  const checkEncoding = (response, statusCode, contentEncoding = '') => {
1359
1377
  switch (statusCode) {
1360
1378
  case 206 /* HTTP_STATUS.PARTIAL_CONTENT */:
1361
- request.emit('error', new Error('[ABORT] Partial content'));
1379
+ request.emit('error', (0, types_1.errorValue)("Aborted" /* ERR_MESSAGE.ABORTED */, 'Partial content'));
1362
1380
  case 204 /* HTTP_STATUS.NO_CONTENT */:
1363
1381
  return;
1364
1382
  }
@@ -1399,7 +1417,7 @@ class Request extends module_1.default {
1399
1417
  const version = this.httpVersion;
1400
1418
  let request, ca, cert, key, minVersion, baseHeaders = this.headersOf(uri);
1401
1419
  if (getting && this.acceptEncoding && !localhost && !baseHeaders?.['accept-encoding']) {
1402
- (_l = (headers || (headers = {})))['accept-encoding'] || (_l['accept-encoding'] = 'gzip, deflate, br' + (LIB_ZSTD ? ', zstd' : ''));
1420
+ (_m = (headers || (headers = {})))['accept-encoding'] || (_m['accept-encoding'] = 'gzip, deflate, br' + (LIB_ZSTD ? ', zstd' : ''));
1403
1421
  }
1404
1422
  if (secure) {
1405
1423
  const certs = this[kCerts]?.[0][origin] || (this.host ? TLS.TEXT[origin] : null);
@@ -1408,7 +1426,7 @@ class Request extends module_1.default {
1408
1426
  }
1409
1427
  }
1410
1428
  if (!proxy && httpVersion !== 1 && ((httpVersion || host.version) === 2 && version !== 1 || secure && version === 2 && host.failed(2, true) === 0)) {
1411
- request = ((_m = this[kSession][0])[origin] || (_m[origin] = http2.connect(origin, { lookup: this.lookupDns(hostname), ca, cert, key, minVersion, settings: localhost ? { initialWindowSize: 4294967295 /* CONSTANTS.INITIAL_WINDOW_SIZE */, maxFrameSize: 16777215 /* CONSTANTS.MAX_FRAME_SIZE */, enablePush: false } : { enablePush: false } }))).request({ ...baseHeaders, ...host_1.default.getBasicAuth(url), ...headers, ':path': pathname, ':method': method });
1429
+ request = ((_o = this[kSession][0])[origin] || (_o[origin] = http2.connect(origin, { lookup: this.lookupDns(hostname), ca, cert, key, minVersion, settings: localhost ? { initialWindowSize: 4294967295 /* CONSTANTS.INITIAL_WINDOW_SIZE */, maxFrameSize: 16777215 /* CONSTANTS.MAX_FRAME_SIZE */, enablePush: false } : { enablePush: false } }))).request({ ...baseHeaders, ...host_1.default.getBasicAuth(url), ...headers, ':path': pathname, ':method': method });
1412
1430
  if (getting) {
1413
1431
  const listenerMap = {};
1414
1432
  const onEvent = request.on.bind(request);
@@ -1442,9 +1460,10 @@ class Request extends module_1.default {
1442
1460
  }
1443
1461
  }
1444
1462
  request.setTimeout(this._config.timeout);
1463
+ this.matchHeaders(url, response, request, options);
1445
1464
  });
1446
1465
  request.on = function (event, listener) {
1447
- var _l;
1466
+ var _m;
1448
1467
  switch (event) {
1449
1468
  case 'data':
1450
1469
  case 'error':
@@ -1454,7 +1473,7 @@ class Request extends module_1.default {
1454
1473
  break;
1455
1474
  }
1456
1475
  if (!connected) {
1457
- (listenerMap[_l = event + '-on'] || (listenerMap[_l] = [])).push(listener);
1476
+ (listenerMap[_m = event + '-on'] || (listenerMap[_m] = [])).push(listener);
1458
1477
  }
1459
1478
  default:
1460
1479
  onEvent(event, listener);
@@ -1463,7 +1482,7 @@ class Request extends module_1.default {
1463
1482
  return this;
1464
1483
  };
1465
1484
  request.once = function (event, listener) {
1466
- var _l;
1485
+ var _m;
1467
1486
  switch (event) {
1468
1487
  case 'data':
1469
1488
  case 'error':
@@ -1473,7 +1492,7 @@ class Request extends module_1.default {
1473
1492
  break;
1474
1493
  }
1475
1494
  if (!connected) {
1476
- (listenerMap[_l = event + '-once'] || (listenerMap[_l] = [])).push(listener);
1495
+ (listenerMap[_m = event + '-once'] || (listenerMap[_m] = [])).push(listener);
1477
1496
  }
1478
1497
  default:
1479
1498
  onceEvent(event, listener);
@@ -1536,8 +1555,8 @@ class Request extends module_1.default {
1536
1555
  agent
1537
1556
  }, response => {
1538
1557
  const statusCode = response.statusCode;
1558
+ const incoming = response.headers;
1539
1559
  if ((getting || posting) && statusCode >= 200 /* HTTP_STATUS.OK */ && statusCode < 300 /* HTTP_STATUS.MULTIPLE_CHOICES */) {
1540
- const incoming = response.headers;
1541
1560
  let source = checkEncoding(response, statusCode, incoming['content-encoding']);
1542
1561
  if (source) {
1543
1562
  source.once('finish', () => request.emit('end'));
@@ -1590,6 +1609,7 @@ class Request extends module_1.default {
1590
1609
  if (this._config.timeout) {
1591
1610
  response.setTimeout(this._config.timeout, () => request.emit('timeout'));
1592
1611
  }
1612
+ this.matchHeaders(url, incoming, request, options);
1593
1613
  });
1594
1614
  options.httpVersion = 1;
1595
1615
  }
@@ -1600,7 +1620,7 @@ class Request extends module_1.default {
1600
1620
  const ac = new AbortController();
1601
1621
  this[kDownloading].add(options.outAbort = ac);
1602
1622
  stream.addAbortSignal(ac.signal, request);
1603
- this.signal.addEventListener('abort', () => ac.abort(), { once: true });
1623
+ this.signal.addEventListener('abort', () => ac.abort(new Error("Aborted by process" /* ERR_MESSAGE.ABORTED_PROCESS */)), { once: true });
1604
1624
  }
1605
1625
  if (posting) {
1606
1626
  if ((0, types_1.isString)(postData) || Buffer.isBuffer(postData)) {
@@ -1765,7 +1785,7 @@ class Request extends module_1.default {
1765
1785
  headers['content-type'] = contentType || "text/plain" /* MIME.TEXT */;
1766
1786
  return this.get(uri, options);
1767
1787
  }
1768
- get(uri, options = {}) {
1788
+ async get(uri, options = {}) {
1769
1789
  const opts = (typeof options === 'string' ? { format: options, encoding: 'utf-8' } : options);
1770
1790
  if (this.readExpect === 'string') {
1771
1791
  opts.encoding = (0, types_1.getEncoding)(opts?.encoding);
@@ -1818,6 +1838,7 @@ class Request extends module_1.default {
1818
1838
  const isRetry = (value) => (0, util_1.isRetryable)(value) && ++retries <= this._config.retryLimit;
1819
1839
  const isUnsupported = (value) => value === 421 /* HTTP_STATUS.MISDIRECTED_REQUEST */ || value === 505 /* HTTP_STATUS.HTTP_VERSION_NOT_SUPPORTED */;
1820
1840
  const isDowngrade = (err) => err instanceof Error && (err.code === 'ERR_HTTP2_ERROR' || isUnsupported(Math.abs(err.errno)));
1841
+ const wasAborted = (err) => err instanceof Error && err.message.startsWith("Aborted" /* ERR_MESSAGE.ABORTED */);
1821
1842
  const formatWarning = (message) => LOG_HTTP && !silent && this.formatMessage(1024 /* LOG_TYPE.HTTP */, 'HTTP' + httpVersion, [message, host.origin], url.toString(), { titleBgColor: 'bgGrey', titleColor: 'yellow' });
1822
1843
  const formatNgFlags = (value, statusCode, location) => location ? `Using HTTP 1.1 for URL redirect (${location})` : formatStatus(statusCode, value ? 'NGHTTP2 Error ' + value : '');
1823
1844
  const abortResponse = () => {
@@ -1930,7 +1951,7 @@ class Request extends module_1.default {
1930
1951
  }
1931
1952
  }
1932
1953
  if (typeof buffer === 'string') {
1933
- if (buffer[0] === '\uFEFF' && encoding !== 'utf16le') {
1954
+ if (buffer.startsWith('\uFEFF') && encoding !== 'utf16le') {
1934
1955
  buffer = buffer.substring(1);
1935
1956
  }
1936
1957
  if (outFormat) {
@@ -2001,7 +2022,10 @@ class Request extends module_1.default {
2001
2022
  };
2002
2023
  const errorResponse = (err) => {
2003
2024
  abortResponse();
2004
- if ((0, util_1.checkRetryable)(err) && ++retries <= this._config.retryLimit) {
2025
+ if (wasAborted(err)) {
2026
+ throwError(err);
2027
+ }
2028
+ else if ((0, util_1.checkRetryable)(err) && ++retries <= this._config.retryLimit) {
2005
2029
  if (isConnectionTimeout(err)) {
2006
2030
  retryTimeout();
2007
2031
  }
@@ -2010,9 +2034,7 @@ class Request extends module_1.default {
2010
2034
  }
2011
2035
  }
2012
2036
  else {
2013
- if (err instanceof Error && !err.message.startsWith('[ABORT]')) {
2014
- host.error(httpVersion);
2015
- }
2037
+ host.error(httpVersion);
2016
2038
  throwError(err);
2017
2039
  }
2018
2040
  };
@@ -2114,6 +2136,10 @@ class Request extends module_1.default {
2114
2136
  if (aborted) {
2115
2137
  return;
2116
2138
  }
2139
+ if (wasAborted(err)) {
2140
+ errorResponse(err);
2141
+ return;
2142
+ }
2117
2143
  switch (!isDowngrade(err) && await host.hasProtocol(2)) {
2118
2144
  case 1 /* QUERY_RESULT.OK */:
2119
2145
  errorResponse(err);
@@ -2191,6 +2217,43 @@ class Request extends module_1.default {
2191
2217
  });
2192
2218
  this[kDownloading].clear();
2193
2219
  }
2220
+ matchHeaders(url, headers, request, options) {
2221
+ const on = this[kHeadersOn];
2222
+ if (on.size) {
2223
+ const href = url.href;
2224
+ const called = new Map();
2225
+ for (const [name, item] of on) {
2226
+ if (name in headers) {
2227
+ for (const [pattern, callback] of item) {
2228
+ if (pattern === '*' || pm.isMatch(href, pattern)) {
2229
+ let data = called.get(callback);
2230
+ if (!data) {
2231
+ called.set(callback, data = {});
2232
+ }
2233
+ data[name] = headers[name];
2234
+ }
2235
+ }
2236
+ }
2237
+ }
2238
+ for (const [callback, data] of called) {
2239
+ try {
2240
+ if (callback(data, url) === true) {
2241
+ const reason = (0, types_1.errorValue)("Aborted by client" /* ERR_MESSAGE.ABORTED_CLIENT */, href);
2242
+ const outAbort = options.outAbort;
2243
+ if (outAbort) {
2244
+ outAbort.abort(reason);
2245
+ this[kDownloading].delete(outAbort);
2246
+ }
2247
+ request.destroy(reason);
2248
+ return;
2249
+ }
2250
+ }
2251
+ catch (err) {
2252
+ this.writeFail(['Unable to process headers', url.origin], err, { type: 1024 /* LOG_TYPE.HTTP */, abortable: this.abortable, fatal: false });
2253
+ }
2254
+ }
2255
+ }
2256
+ }
2194
2257
  set agentTimeout(value) {
2195
2258
  if (value > 0) {
2196
2259
  this[kAgentTimeout] = value;
@@ -2228,11 +2291,11 @@ class Request extends module_1.default {
2228
2291
  return this[kIpVersion];
2229
2292
  }
2230
2293
  get settings() {
2231
- var _l;
2232
- return (_l = this.module).settings || (_l.settings = {});
2294
+ var _m;
2295
+ return (_m = this.module).settings || (_m.settings = {});
2233
2296
  }
2234
2297
  }
2235
- _a = kSingleton, _b = kHttpVersion, _c = kHeaders, _d = kCerts, _e = kConnectDns, _f = kPendingDns, _g = kConnectHttp, _h = kDownloading, _j = kHostInfo, _k = kSession;
2298
+ _a = kSingleton, _b = kHttpVersion, _c = kHeaders, _d = kCerts, _e = kConnectDns, _f = kPendingDns, _g = kConnectHttp, _h = kDownloading, _j = kHostInfo, _k = kSession, _l = kHeadersOn;
2236
2299
  exports.default = Request;
2237
2300
 
2238
2301
  if (exports.default) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e-mc/request",
3
- "version": "0.7.1",
3
+ "version": "0.8.1",
4
4
  "description": "Request constructor for E-mc.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -20,10 +20,11 @@
20
20
  "license": "BSD 3-Clause",
21
21
  "homepage": "https://github.com/anpham6/e-mc#readme",
22
22
  "dependencies": {
23
- "@e-mc/module": "0.7.1",
24
- "@e-mc/types": "0.7.1",
23
+ "@e-mc/module": "0.8.1",
24
+ "@e-mc/types": "0.8.1",
25
25
  "combined-stream": "^1.0.8",
26
26
  "js-yaml": "^4.1.0",
27
+ "picomatch": "^3.0.1",
27
28
  "which": "^2.0.2"
28
29
  }
29
30
  }