@e-mc/request 0.8.27 → 0.8.29

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/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  ## Interface
11
11
 
12
- - https://www.unpkg.com/@e-mc/types@0.8.27/lib/index.d.ts
12
+ - https://www.unpkg.com/@e-mc/types@0.8.29/lib/index.d.ts
13
13
 
14
14
  ```typescript
15
15
  import type { IModule, ModuleConstructor } from "./index";
@@ -82,9 +82,9 @@ interface RequestConstructor extends ModuleConstructor {
82
82
 
83
83
  ## References
84
84
 
85
- - https://www.unpkg.com/@e-mc/types@0.8.27/lib/http.d.ts
86
- - https://www.unpkg.com/@e-mc/types@0.8.27/lib/request.d.ts
87
- - https://www.unpkg.com/@e-mc/types@0.8.27/lib/settings.d.ts
85
+ - https://www.unpkg.com/@e-mc/types@0.8.29/lib/http.d.ts
86
+ - https://www.unpkg.com/@e-mc/types@0.8.29/lib/request.d.ts
87
+ - https://www.unpkg.com/@e-mc/types@0.8.29/lib/settings.d.ts
88
88
 
89
89
  ## LICENSE
90
90
 
@@ -5,28 +5,28 @@ const yaml = require("js-yaml");
5
5
  const types_1 = require("@e-mc/types");
6
6
  const module_1 = require("@e-mc/module");
7
7
  const util_1 = require("@e-mc/request/util");
8
+ const kHttpAdapter = Symbol.for('request:http:adapter:constructor');
8
9
  let LOG_TIMEFORMAT = 'readable';
10
+ const isConstructor = (value) => typeof value === 'function' && !!value.prototype?.constructor.name;
9
11
  class HttpAdapter {
10
12
  instance;
11
13
  state;
12
14
  uri;
15
+ static [kHttpAdapter] = true;
16
+ static constructorOf(value) {
17
+ return isConstructor(value) && value[kHttpAdapter] === true;
18
+ }
13
19
  static isUnsupported(value) {
14
20
  return value === 421 || value === 505;
15
21
  }
16
22
  static isDowngrade(err) {
17
- return err instanceof Error && (err.code === 'ERR_HTTP2_ERROR' || this.isUnsupported(Math.abs(err.errno)));
23
+ return (0, types_1.isErrorCode)(err, 'ERR_HTTP2_ERROR') || err instanceof Error && this.isUnsupported(Math.abs(err.errno));
18
24
  }
19
25
  static wasAborted(err) {
20
26
  return err instanceof Error && err.message.startsWith("Aborted");
21
27
  }
22
28
  static isConnectionError(err) {
23
- switch (err instanceof Error && err.code) {
24
- case 'ETIMEDOUT':
25
- case 'ECONNRESET':
26
- return true;
27
- default:
28
- return false;
29
- }
29
+ return (0, types_1.isErrorCode)(err, 'ETIMEDOUT', 'ECONNRESET');
30
30
  }
31
31
  static defineHostConfig({ settings }) {
32
32
  const time_format = settings?.time_format;
@@ -79,13 +79,21 @@ class HttpAdapter {
79
79
  return;
80
80
  }
81
81
  const statusCode = headers[':status'];
82
- if (statusCode < 300) {
83
- this.acceptResponse(headers);
82
+ if (statusCode === 204 || statusCode === 304) {
83
+ this.acceptResponse(headers, true);
84
+ }
85
+ else if (statusCode < 300) {
86
+ this.acceptResponse(headers, false);
84
87
  }
85
- else if (statusCode < 400) {
88
+ else if (statusCode === 301 ||
89
+ statusCode === 302 ||
90
+ statusCode === 303 ||
91
+ statusCode === 307 ||
92
+ statusCode === 308) {
86
93
  this.redirectResponse(statusCode, headers.location);
87
94
  }
88
- else if (statusCode === 401 ||
95
+ else if (statusCode === 305 ||
96
+ statusCode === 401 ||
89
97
  statusCode === 402 ||
90
98
  statusCode === 403 ||
91
99
  statusCode === 404 ||
@@ -151,10 +159,17 @@ class HttpAdapter {
151
159
  return;
152
160
  }
153
161
  const statusCode = res.statusCode;
154
- if (statusCode < 300) {
155
- this.acceptResponse(res.headers);
162
+ if (statusCode === 204 || statusCode === 304) {
163
+ this.acceptResponse(res.headers, true);
156
164
  }
157
- else if (statusCode < 400) {
165
+ else if (statusCode < 300) {
166
+ this.acceptResponse(res.headers, false);
167
+ }
168
+ else if (statusCode === 301 ||
169
+ statusCode === 302 ||
170
+ statusCode === 303 ||
171
+ statusCode === 307 ||
172
+ statusCode === 308) {
158
173
  this.redirectResponse(statusCode, res.headers.location);
159
174
  }
160
175
  else if (this.isRetry(statusCode)) {
@@ -226,7 +241,7 @@ class HttpAdapter {
226
241
  this.opts.httpVersion = 1;
227
242
  this.init();
228
243
  }
229
- acceptResponse(headers) {
244
+ acceptResponse(headers, empty = false) {
230
245
  const opts = this.opts;
231
246
  if ('outHeaders' in opts) {
232
247
  opts.outHeaders = headers;
@@ -238,7 +253,7 @@ class HttpAdapter {
238
253
  const enabled = opts.connected?.call(this.client, headers) !== false && !pipeline;
239
254
  const maxBufferSize = opts.maxBufferSize ? (0, types_1.alignSize)(opts.maxBufferSize) : 0;
240
255
  this.contentLength = parseInt(headers['content-length'] || '0');
241
- const updating = opts.progressId !== undefined && !!this.instance.host && this.contentLength > 0;
256
+ const updating = opts.progressId !== undefined && !!this.instance.host && this.contentLength > 0 && !empty;
242
257
  const readTimeout = this.instance.readTimeout;
243
258
  let log = this.state.log, buffer = null, dataLength = 0;
244
259
  this.client.once('readable', () => {
@@ -267,7 +282,7 @@ class HttpAdapter {
267
282
  this.updateProgress(0, 0);
268
283
  }
269
284
  });
270
- if (enabled) {
285
+ if (enabled && !empty) {
271
286
  const encoding = opts.encoding;
272
287
  this.client.on('data', (chunk) => {
273
288
  if (buffer) {
@@ -340,7 +355,12 @@ class HttpAdapter {
340
355
  result = new (require(packageName = 'fast-xml-parser').XMLParser)(parser).parse(buffer);
341
356
  break;
342
357
  case 'toml':
343
- result = require(packageName = 'toml').parse(buffer);
358
+ try {
359
+ result = require('smol-toml').parse(buffer);
360
+ }
361
+ catch {
362
+ result = require(packageName = 'toml').parse(buffer);
363
+ }
344
364
  break;
345
365
  default:
346
366
  result = JSON.parse(buffer);
@@ -366,7 +386,7 @@ class HttpAdapter {
366
386
  if (updating) {
367
387
  this.updateProgress(0, this.contentLength);
368
388
  }
369
- if (enabled && this.instance.readExpect === 'always') {
389
+ if (enabled && this.instance.readExpect === 'always' && !empty) {
370
390
  this.terminate("No data received");
371
391
  return;
372
392
  }
@@ -402,6 +422,9 @@ class HttpAdapter {
402
422
  }
403
423
  else if (++this.redirects <= this.redirectLimit) {
404
424
  this.abortResponse();
425
+ if (this.opts.method?.toUpperCase() === 'PUT' && statusCode !== 307 && statusCode !== 308) {
426
+ this.#options.method = 'GET';
427
+ }
405
428
  this.setOpts((0, util_1.fromURL)(this.opts.url, location));
406
429
  this.init();
407
430
  }
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ class HttpHostAltSvc {
3
+ host;
4
+ #location = {};
5
+ #available = [];
6
+ #errors = [];
7
+ #versionData;
8
+ constructor(host, versionData) {
9
+ this.host = host;
10
+ this.#versionData = versionData;
11
+ }
12
+ did(version) {
13
+ return this.#versionData[version].status !== -1;
14
+ }
15
+ next() {
16
+ const queue = this.#available.shift();
17
+ if (queue) {
18
+ const { hostname, port, version, expires } = queue;
19
+ const ms = expires - Date.now();
20
+ if (ms < 0) {
21
+ return this.next();
22
+ }
23
+ let timeout = null;
24
+ if (!isNaN(ms)) {
25
+ timeout = setTimeout(() => {
26
+ if (!this.next()) {
27
+ this.host.version = 1;
28
+ }
29
+ }, ms);
30
+ }
31
+ this.#location = { hostname, port, version, timeout, origin: this.host.protocol + '//' + hostname + ':' + port };
32
+ return true;
33
+ }
34
+ return false;
35
+ }
36
+ close(error) {
37
+ const { hostname, port, version, timeout } = this.#location;
38
+ if (hostname) {
39
+ this.#location = {};
40
+ if (timeout) {
41
+ clearTimeout(timeout);
42
+ }
43
+ if (error) {
44
+ this.#errors.push({ hostname, port, version });
45
+ return this.next();
46
+ }
47
+ }
48
+ return false;
49
+ }
50
+ clear(version) {
51
+ if (version) {
52
+ if (this.#available.length === 0) {
53
+ this.flag(version, 0);
54
+ }
55
+ else if (!this.close(true)) {
56
+ this.flag(version, -1);
57
+ }
58
+ }
59
+ else {
60
+ this.close();
61
+ this.#available = [];
62
+ this.#errors = [];
63
+ for (const item of this.#versionData) {
64
+ if (item.alpn !== 0) {
65
+ item.status = -1;
66
+ }
67
+ }
68
+ }
69
+ }
70
+ flag(version, value) {
71
+ this.#versionData[version - 1].status = value;
72
+ }
73
+ valid(hostname, port, version) {
74
+ return !this.errors.find(item => item.hostname === hostname && item.port === port && item.version === version);
75
+ }
76
+ set available(value) {
77
+ this.#available = value;
78
+ }
79
+ get errors() {
80
+ return this.#errors;
81
+ }
82
+ get hostname() {
83
+ return this.#location.hostname;
84
+ }
85
+ get port() {
86
+ return this.#location.port;
87
+ }
88
+ get origin() {
89
+ return this.#location.origin;
90
+ }
91
+ }
92
+ module.exports = HttpHostAltSvc;
package/index.js CHANGED
@@ -159,11 +159,17 @@ function getProxySettings(request, agentTimeout) {
159
159
  return null;
160
160
  }
161
161
  function closeTorrent(pid) {
162
- const index = ARIA2.PID_QUEUE.findIndex(value => pid === value[0]);
162
+ const index = ARIA2.PID_QUEUE.findIndex(value => value[0] === pid);
163
163
  if (index !== -1) {
164
164
  ARIA2.PID_QUEUE.splice(index, 1);
165
165
  }
166
166
  }
167
+ function resetAria2() {
168
+ if (ARIA2.PID_TIMER) {
169
+ clearInterval(ARIA2.PID_TIMER);
170
+ ARIA2.PID_TIMER = null;
171
+ }
172
+ }
167
173
  function clearDnsLookup() {
168
174
  DNS.CACHE = Object.create(null);
169
175
  DNS.TIMEOUT.forEach(value => clearTimeout(value));
@@ -181,7 +187,7 @@ function resetHttpHost(version) {
181
187
  const host = HTTP.HOST[origin];
182
188
  if (host.secure && host.version === 1) {
183
189
  const failed = host.failed(2, true);
184
- if (failed === 0 && host.failed(2, true) < 10 || failed < 3 && host.success(2, true) > 0) {
190
+ if (failed === 0 && host.error(2, true) < 10 || failed < 3 && host.success(2, true) > 0) {
185
191
  host.version = version;
186
192
  }
187
193
  }
@@ -266,6 +272,8 @@ function checkEncoding(request, response, statusCode, outStream, contentEncoding
266
272
  case 206:
267
273
  request.emit('error', (0, types_1.errorValue)("Aborted", 'Partial content'));
268
274
  case 204:
275
+ case 205:
276
+ case 304:
269
277
  return;
270
278
  default:
271
279
  contentEncoding = contentEncoding.trim();
@@ -666,7 +674,7 @@ class Request extends module_1.default {
666
674
  break;
667
675
  }
668
676
  if (expires !== undefined) {
669
- if (typeof expires === 'string') {
677
+ if ((0, types_1.isString)(expires)) {
670
678
  expires = (0, types_1.parseExpires)(expires);
671
679
  }
672
680
  if (expires >= 0) {
@@ -897,8 +905,12 @@ class Request extends module_1.default {
897
905
  }
898
906
  break;
899
907
  case 'readExpect':
900
- if ((0, types_1.isString)(value)) {
901
- this[name] = value;
908
+ switch (value) {
909
+ case 'string':
910
+ case 'always':
911
+ case 'none':
912
+ this[name] = value;
913
+ break;
902
914
  }
903
915
  break;
904
916
  }
@@ -1368,13 +1380,9 @@ class Request extends module_1.default {
1368
1380
  stderr.setEncoding('utf-8').on('data', (value) => message += value);
1369
1381
  if (pid !== undefined && module_1.default.isFile(uri, 'torrent')) {
1370
1382
  if (!ARIA2.PID_TIMER) {
1371
- const clearTimer = () => {
1372
- clearInterval(ARIA2.PID_TIMER);
1373
- ARIA2.PID_TIMER = null;
1374
- };
1375
1383
  ARIA2.PID_TIMER = setInterval(() => {
1376
1384
  if (ARIA2.PID_QUEUE.length === 0) {
1377
- clearTimer();
1385
+ resetAria2();
1378
1386
  return;
1379
1387
  }
1380
1388
  for (const item of ARIA2.PID_QUEUE) {
@@ -1409,7 +1417,7 @@ class Request extends module_1.default {
1409
1417
  ARIA2.PID_QUEUE.push(item);
1410
1418
  }
1411
1419
  else {
1412
- clearTimer();
1420
+ resetAria2();
1413
1421
  }
1414
1422
  }
1415
1423
  }, (ARIA2.UPDATE_STATUS || 30) * 1000);
@@ -1942,7 +1950,7 @@ class Request extends module_1.default {
1942
1950
  formatWarning(`Connection timeout (${retries} / ${this._config.retryLimit})`);
1943
1951
  downloadUri.call(this, href);
1944
1952
  };
1945
- const acceptResponse = (headers) => {
1953
+ const acceptResponse = (headers, empty) => {
1946
1954
  var _o;
1947
1955
  if ('outHeaders' in opts) {
1948
1956
  opts.outHeaders = headers;
@@ -1976,7 +1984,7 @@ class Request extends module_1.default {
1976
1984
  }
1977
1985
  });
1978
1986
  }
1979
- if (enabled) {
1987
+ if (enabled && !empty) {
1980
1988
  client.on('data', (chunk) => {
1981
1989
  if (buffer) {
1982
1990
  if (typeof buffer === 'string') {
@@ -2067,7 +2075,7 @@ class Request extends module_1.default {
2067
2075
  result = buffer;
2068
2076
  }
2069
2077
  }
2070
- else if (enabled && this.readExpect === 'always') {
2078
+ else if (enabled && !empty && this.readExpect === 'always') {
2071
2079
  throwError('No data received');
2072
2080
  return;
2073
2081
  }
@@ -2166,13 +2174,21 @@ class Request extends module_1.default {
2166
2174
  return;
2167
2175
  }
2168
2176
  const statusCode = headers[':status'];
2169
- if (statusCode < 300) {
2170
- acceptResponse(headers);
2177
+ if (statusCode === 204 || statusCode === 304) {
2178
+ acceptResponse(headers, true);
2179
+ }
2180
+ else if (statusCode < 300) {
2181
+ acceptResponse(headers, false);
2171
2182
  }
2172
- else if (statusCode < 400) {
2183
+ else if (statusCode === 301 ||
2184
+ statusCode === 302 ||
2185
+ statusCode === 303 ||
2186
+ statusCode === 307 ||
2187
+ statusCode === 308) {
2173
2188
  redirectResponse(statusCode, headers.location);
2174
2189
  }
2175
- else if (statusCode === 401 ||
2190
+ else if (statusCode === 305 ||
2191
+ statusCode === 401 ||
2176
2192
  statusCode === 402 ||
2177
2193
  statusCode === 403 ||
2178
2194
  statusCode === 404 ||
@@ -2236,10 +2252,17 @@ class Request extends module_1.default {
2236
2252
  return;
2237
2253
  }
2238
2254
  const statusCode = res.statusCode;
2239
- if (statusCode < 300) {
2240
- acceptResponse(res.headers);
2255
+ if (statusCode === 204 || statusCode === 304) {
2256
+ acceptResponse(res.headers, true);
2257
+ }
2258
+ else if (statusCode < 300) {
2259
+ acceptResponse(res.headers, false);
2241
2260
  }
2242
- else if (statusCode < 400) {
2261
+ else if (statusCode === 301 ||
2262
+ statusCode === 302 ||
2263
+ statusCode === 303 ||
2264
+ statusCode === 307 ||
2265
+ statusCode === 308) {
2243
2266
  redirectResponse(statusCode, res.headers.location);
2244
2267
  }
2245
2268
  else if (isRetry(statusCode)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e-mc/request",
3
- "version": "0.8.27",
3
+ "version": "0.8.29",
4
4
  "description": "Request constructor for E-mc.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -20,8 +20,8 @@
20
20
  "license": "MIT",
21
21
  "homepage": "https://github.com/anpham6/e-mc#readme",
22
22
  "dependencies": {
23
- "@e-mc/module": "0.8.27",
24
- "@e-mc/types": "0.8.27",
23
+ "@e-mc/module": "0.8.29",
24
+ "@e-mc/types": "0.8.29",
25
25
  "combined-stream": "^1.0.8",
26
26
  "js-yaml": "^4.1.0",
27
27
  "picomatch": "^3.0.1",