@e-mc/request 0.8.6 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +10 -10
- package/README.md +145 -8
- package/http/host/index.d.ts +4 -4
- package/http/host/index.js +7 -15
- package/index.d.ts +4 -4
- package/index.js +114 -100
- package/package.json +4 -4
- package/util.d.ts +9 -0
- package/util.js +79 -7
package/LICENSE
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
Copyright 2024 An Pham
|
|
2
|
-
|
|
3
|
-
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
4
|
-
|
|
5
|
-
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
6
|
-
|
|
7
|
-
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
8
|
-
|
|
9
|
-
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
10
|
-
|
|
1
|
+
Copyright 2024 An Pham
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
4
|
+
|
|
5
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
6
|
+
|
|
7
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
8
|
+
|
|
9
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
10
|
+
|
|
11
11
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @e-mc/request
|
|
2
2
|
|
|
3
|
-
* NodeJS 14
|
|
3
|
+
* NodeJS 14/16
|
|
4
4
|
* ES2020
|
|
5
5
|
|
|
6
6
|
## General Usage
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
## Interface
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
* [View Source](https://www.unpkg.com/@e-mc/types@0.9.0/lib/index.d.ts)
|
|
13
13
|
|
|
14
14
|
```typescript
|
|
15
15
|
import type { IModule, ModuleConstructor } from "./index";
|
|
@@ -32,13 +32,13 @@ interface IRequest extends IModule {
|
|
|
32
32
|
init(config?: RequestInit): this;
|
|
33
33
|
apply(options: ApplyOptions): this;
|
|
34
34
|
addDns(hostname: string, address: string, timeout: number): void;
|
|
35
|
-
addDns(hostname: string, address: string, family?:
|
|
35
|
+
addDns(hostname: string, address: string, family?: string, timeout?: number): void;
|
|
36
36
|
lookupDns(hostname: string): LookupFunction;
|
|
37
37
|
proxyOf(uri: string, localhost?: boolean): ProxySettings | undefined;
|
|
38
38
|
statusOn(name: number | number[], callback: StatusOnCallback): void;
|
|
39
|
-
statusOn(name: number | number[],
|
|
39
|
+
statusOn(name: number | number[], globUrl: string, callback: StatusOnCallback): void;
|
|
40
40
|
headersOn(name: string | string[], callback: HeadersOnCallback): void;
|
|
41
|
-
headersOn(name: string | string[],
|
|
41
|
+
headersOn(name: string | string[], globUrl: string, callback: HeadersOnCallback): void;
|
|
42
42
|
headersOf(uri: string): OutgoingHttpHeaders | undefined;
|
|
43
43
|
aria2c(uri: string | URL, pathname: string): Promise<string[]>;
|
|
44
44
|
aria2c(uri: string | URL, options?: Aria2Options): Promise<string[]>;
|
|
@@ -80,11 +80,148 @@ interface RequestConstructor extends ModuleConstructor {
|
|
|
80
80
|
}
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
+
## Settings
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import type { PermittedDirectories } from "./core";
|
|
87
|
+
import type { SecureConfig } from "./http";
|
|
88
|
+
import type { PurgeComponent } from "./settings";
|
|
89
|
+
|
|
90
|
+
import type { LookupAddress } from "dns";
|
|
91
|
+
import type { OutgoingHttpHeaders } from "http";
|
|
92
|
+
|
|
93
|
+
interface RequestModule {
|
|
94
|
+
handler: "@e-mc/request";
|
|
95
|
+
timeout?: number | string;
|
|
96
|
+
read_timeout?: number | string;
|
|
97
|
+
agent?: {
|
|
98
|
+
keep_alive?: boolean;
|
|
99
|
+
timeout?: number | string;
|
|
100
|
+
};
|
|
101
|
+
connect?: {
|
|
102
|
+
timeout?: number | string;
|
|
103
|
+
retry_wait?: number | string;
|
|
104
|
+
retry_after?: number | string;
|
|
105
|
+
retry_limit?: number;
|
|
106
|
+
redirect_limit?: number;
|
|
107
|
+
};
|
|
108
|
+
dns?: {
|
|
109
|
+
family?: number;
|
|
110
|
+
expires?: number | string;
|
|
111
|
+
resolve?: Record<string, Partial<LookupAddress>>;
|
|
112
|
+
};
|
|
113
|
+
use?: {
|
|
114
|
+
http_version?: 1 | 2;
|
|
115
|
+
accept_encoding?: boolean;
|
|
116
|
+
};
|
|
117
|
+
proxy?: {
|
|
118
|
+
address?: string;
|
|
119
|
+
port?: number;
|
|
120
|
+
username?: string;
|
|
121
|
+
password?: string;
|
|
122
|
+
include?: string[];
|
|
123
|
+
exclude?: string[];
|
|
124
|
+
keep_alive?: boolean;
|
|
125
|
+
};
|
|
126
|
+
headers: Record<string, OutgoingHttpHeaders>;
|
|
127
|
+
certs?: Record<string, SecureConfig<string | string[]>>;
|
|
128
|
+
localhost?: string[];
|
|
129
|
+
protocol?: {
|
|
130
|
+
"http/1.1"?: string[];
|
|
131
|
+
h2c?: string[];
|
|
132
|
+
h2?: string[];
|
|
133
|
+
};
|
|
134
|
+
post_limit?: number | string;
|
|
135
|
+
settings?: {
|
|
136
|
+
broadcast_id?: string | string[];
|
|
137
|
+
time_format?: "readable" | "relative" | "none";
|
|
138
|
+
purge?: PurgeComponent;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
interface DownloadModule {
|
|
143
|
+
expires?: number | string;
|
|
144
|
+
aria2?: {
|
|
145
|
+
bin?: string | false;
|
|
146
|
+
exec?: {
|
|
147
|
+
uid?: number;
|
|
148
|
+
gid?: number;
|
|
149
|
+
};
|
|
150
|
+
update_status?: number | { interval?: number; broadcast_only?: boolean };
|
|
151
|
+
max_concurrent_downloads?: number;
|
|
152
|
+
max_connection_per_server?: number;
|
|
153
|
+
bt_stop_timeout?: number;
|
|
154
|
+
bt_tracker_connect_timeout?: number;
|
|
155
|
+
bt_tracker_timeout?: number;
|
|
156
|
+
min_split_size?: string;
|
|
157
|
+
disk_cache?: number | string;
|
|
158
|
+
lowest_speed_limit?: number | string;
|
|
159
|
+
always_resume?: boolean;
|
|
160
|
+
file_allocation?: "none" | "prealloc" | "trunc" | "falloc";
|
|
161
|
+
conf_path?: string;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Example usage
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
const Request = require("@e-mc/request");
|
|
170
|
+
|
|
171
|
+
const instance = new Request({
|
|
172
|
+
read_timeout: 30,
|
|
173
|
+
connect: {
|
|
174
|
+
timeout: 20, // Seconds
|
|
175
|
+
retry_wait: 1,
|
|
176
|
+
retry_after: 30,
|
|
177
|
+
retry_limit: 3, // Max attempts
|
|
178
|
+
redirect_limit: 10
|
|
179
|
+
},
|
|
180
|
+
use: {
|
|
181
|
+
http_version: 2,
|
|
182
|
+
accept_encoding: true
|
|
183
|
+
},
|
|
184
|
+
dns: {
|
|
185
|
+
family: 4 // ipVersion
|
|
186
|
+
},
|
|
187
|
+
agent: { keep_alive: true }
|
|
188
|
+
});
|
|
189
|
+
request.init({ ipVersion: 6 });
|
|
190
|
+
|
|
191
|
+
const options = {
|
|
192
|
+
format: "yaml",
|
|
193
|
+
httpVersion: 1,
|
|
194
|
+
silent: true,
|
|
195
|
+
headers: { "x-goog-user-project": "project-1" }
|
|
196
|
+
};
|
|
197
|
+
instance.get("http://hostname/path/config.yml", options).then(data => {
|
|
198
|
+
console.log(data.property);
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## NodeJS 14 LTS
|
|
203
|
+
|
|
204
|
+
Any optional fail safe dependencies were removed as of `E-mc 0.9`. The code itself will still be *ES2020* and will continue to work equivalently when self-installing these dependencies:
|
|
205
|
+
|
|
206
|
+
### Under 15.4 + 16.0
|
|
207
|
+
|
|
208
|
+
```sh
|
|
209
|
+
npm i abort-controller event-target-shim
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Under 14.17 + 15.6
|
|
213
|
+
|
|
214
|
+
```sh
|
|
215
|
+
npm i uuid
|
|
216
|
+
```
|
|
217
|
+
|
|
83
218
|
## References
|
|
84
219
|
|
|
85
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
86
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
87
|
-
- https://www.unpkg.com/@e-mc/types@0.
|
|
220
|
+
- https://www.unpkg.com/@e-mc/types@0.9.0/lib/http.d.ts
|
|
221
|
+
- https://www.unpkg.com/@e-mc/types@0.9.0/lib/request.d.ts
|
|
222
|
+
- https://www.unpkg.com/@e-mc/types@0.9.0/lib/settings.d.ts
|
|
223
|
+
|
|
224
|
+
* https://www.npmjs.com/package/@types/node
|
|
88
225
|
|
|
89
226
|
## LICENSE
|
|
90
227
|
|
package/http/host/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { HttpHostConstructor } from '../../../types/lib/request';
|
|
2
|
-
|
|
3
|
-
declare const HttpHost: HttpHostConstructor;
|
|
4
|
-
|
|
1
|
+
import type { HttpHostConstructor } from '../../../types/lib/request';
|
|
2
|
+
|
|
3
|
+
declare const HttpHost: HttpHostConstructor;
|
|
4
|
+
|
|
5
5
|
export = HttpHost;
|
package/http/host/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var _a, _b, _c, _d;
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
3
|
const tls = require("tls");
|
|
5
|
-
const types_1 = require("@e-mc/types");
|
|
6
4
|
const kProtocol = Symbol('protocol');
|
|
7
5
|
const kSecure = Symbol('secure');
|
|
8
6
|
const kHostname = Symbol('hostname');
|
|
@@ -27,7 +25,7 @@ const HOST_ALPN_H2 = [];
|
|
|
27
25
|
})();
|
|
28
26
|
class HttpHost {
|
|
29
27
|
static normalizeOrigin(value) {
|
|
30
|
-
return value.replace(/\/+$/, '') + (!/:\d+$/.test(value) ? ':' + (value.startsWith('https') ? '443' : '80') : '');
|
|
28
|
+
return (value = value.trim()).replace(/\/+$/, '') + (!/:\d+$/.test(value) ? ':' + (value.startsWith('https') ? '443' : '80') : '');
|
|
31
29
|
}
|
|
32
30
|
static formatBasicAuth(url) {
|
|
33
31
|
return url.username ? decodeURIComponent(url.username) + (url.password ? ':' + decodeURIComponent(url.password) : '') : '';
|
|
@@ -40,19 +38,19 @@ class HttpHost {
|
|
|
40
38
|
}
|
|
41
39
|
static defineLocalHost(value) {
|
|
42
40
|
HOST_LOCAL.clear();
|
|
43
|
-
value.forEach(address =>
|
|
41
|
+
value.forEach(address => HOST_LOCAL.add(address));
|
|
44
42
|
}
|
|
45
43
|
static defineProtocolNegotiation(value) {
|
|
46
44
|
const { h2c, h2 } = value;
|
|
47
45
|
const http11 = value['http/1.1'];
|
|
48
46
|
if (Array.isArray(http11)) {
|
|
49
|
-
HOST_HTTP_1_1.push(...http11.map(address => this.normalizeOrigin(address
|
|
47
|
+
HOST_HTTP_1_1.push(...http11.map(address => this.normalizeOrigin(address)));
|
|
50
48
|
}
|
|
51
49
|
if (Array.isArray(h2c)) {
|
|
52
|
-
HOST_ALPN_H2C.push(...h2c.map(address => this.normalizeOrigin(address
|
|
50
|
+
HOST_ALPN_H2C.push(...h2c.map(address => this.normalizeOrigin(address)));
|
|
53
51
|
}
|
|
54
52
|
if (Array.isArray(h2)) {
|
|
55
|
-
HOST_ALPN_H2.push(...h2.map(address => this.normalizeOrigin(address
|
|
53
|
+
HOST_ALPN_H2.push(...h2.map(address => this.normalizeOrigin(address)));
|
|
56
54
|
}
|
|
57
55
|
}
|
|
58
56
|
constructor(url, httpVersion = 1) {
|
|
@@ -173,13 +171,11 @@ class HttpHost {
|
|
|
173
171
|
}
|
|
174
172
|
return false;
|
|
175
173
|
};
|
|
176
|
-
const pattern = new RegExp(`h${i + 1}(?:-\\d+)?="([^:]*):(\\d+)"([^,]*)`, 'g');
|
|
177
174
|
const addresses = [];
|
|
178
175
|
const time = Date.now();
|
|
179
176
|
const hostname = this[kHostname];
|
|
180
177
|
const excluded = this[kAltSvcError];
|
|
181
|
-
|
|
182
|
-
while (match = pattern.exec(altSvc)) {
|
|
178
|
+
for (const match of altSvc.matchAll(new RegExp(`h${i + 1}(?:-\\d+)?="([^:]*):(\\d+)"([^,]*)`, 'g'))) {
|
|
183
179
|
const port = match[2];
|
|
184
180
|
if (!match[1] && port === this.port) {
|
|
185
181
|
increment(2);
|
|
@@ -327,9 +323,5 @@ class HttpHost {
|
|
|
327
323
|
}
|
|
328
324
|
}
|
|
329
325
|
_a = kVersionData, _b = kAltSvc, _c = kAltSvcQueue, _d = kAltSvcError;
|
|
330
|
-
exports.default = HttpHost;
|
|
331
326
|
|
|
332
|
-
|
|
333
|
-
module.exports = exports.default;
|
|
334
|
-
module.exports.default = exports.default;
|
|
335
|
-
}
|
|
327
|
+
module.exports = HttpHost;
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { RequestConstructor } from '../types/lib';
|
|
2
|
-
|
|
3
|
-
declare const Request: RequestConstructor;
|
|
4
|
-
|
|
1
|
+
import type { RequestConstructor } from '../types/lib';
|
|
2
|
+
|
|
3
|
+
declare const Request: RequestConstructor;
|
|
4
|
+
|
|
5
5
|
export = Request;
|
package/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
3
|
const path = require("path");
|
|
5
4
|
const fs = require("fs");
|
|
6
5
|
const child_process = require("child_process");
|
|
@@ -16,7 +15,6 @@ const combined = require("combined-stream");
|
|
|
16
15
|
const pm = require("picomatch");
|
|
17
16
|
const yaml = require("js-yaml");
|
|
18
17
|
const which = require("which");
|
|
19
|
-
const lib_v4_1 = require("@e-mc/module/lib-v4");
|
|
20
18
|
const types_1 = require("@e-mc/types");
|
|
21
19
|
const module_1 = require("@e-mc/module");
|
|
22
20
|
const host_1 = require("@e-mc/request/http/host");
|
|
@@ -36,8 +34,8 @@ const kConnectHttp = Symbol('connectHttp');
|
|
|
36
34
|
const kStatusOn = Symbol('statusOn');
|
|
37
35
|
const kHeadersOn = Symbol('headersOn');
|
|
38
36
|
const PLATFORM_WIN32 = process.platform === 'win32';
|
|
39
|
-
const SUPPORT_NODEJS20 = module_1.
|
|
40
|
-
const SUPPORT_ABORTSIGNAL = module_1.
|
|
37
|
+
const SUPPORT_NODEJS20 = module_1.supported(20);
|
|
38
|
+
const SUPPORT_ABORTSIGNAL = module_1.supported(15, 3) || module_1.supported(14, 17, 0, true);
|
|
41
39
|
const HTTP = {
|
|
42
40
|
HOST: {},
|
|
43
41
|
HEADERS: {},
|
|
@@ -139,10 +137,10 @@ function getProxySettings(request, agentTimeout) {
|
|
|
139
137
|
const proxy = request.proxy;
|
|
140
138
|
if (proxy?.address && proxy.port) {
|
|
141
139
|
const port = (0, util_1.asInt)(proxy.port);
|
|
142
|
-
const address = (!module_1.
|
|
140
|
+
const address = (!module_1.isURL(proxy.address) ? port === 80 ? 'http://' : 'https://' : '') + proxy.address;
|
|
143
141
|
try {
|
|
144
142
|
let host = new URL(address + ':' + port), include, exclude;
|
|
145
|
-
if (
|
|
143
|
+
if (proxy.username) {
|
|
146
144
|
host = new URL(host.protocol + '//' + (0, util_1.getBasicAuth)(proxy.username, proxy.password) + host.host);
|
|
147
145
|
}
|
|
148
146
|
if ((0, types_1.isArray)(proxy.include)) {
|
|
@@ -199,7 +197,7 @@ function validateCerts(certs) {
|
|
|
199
197
|
const file = {};
|
|
200
198
|
const checkFile = (values) => {
|
|
201
199
|
for (let pathname of values) {
|
|
202
|
-
if (module_1.
|
|
200
|
+
if (module_1.isPath(pathname = path.resolve(pathname))) {
|
|
203
201
|
return pathname;
|
|
204
202
|
}
|
|
205
203
|
}
|
|
@@ -270,7 +268,7 @@ function abortHeaders(href, request, options) {
|
|
|
270
268
|
}
|
|
271
269
|
request.destroy(reason);
|
|
272
270
|
}
|
|
273
|
-
class Request extends module_1
|
|
271
|
+
class Request extends module_1 {
|
|
274
272
|
static async purgeMemory(percent = 1, limit = 0, parent) {
|
|
275
273
|
if (percent >= 1) {
|
|
276
274
|
resetHttpHost();
|
|
@@ -414,7 +412,7 @@ class Request extends module_1.default {
|
|
|
414
412
|
}
|
|
415
413
|
LOG_HTTP = this.hasLogType(1024);
|
|
416
414
|
LOG_TIMEPROCESS = this.hasLogType(256);
|
|
417
|
-
LOG_STDOUT = module_1.
|
|
415
|
+
LOG_STDOUT = module_1.hasLogType(32768);
|
|
418
416
|
return true;
|
|
419
417
|
}
|
|
420
418
|
static readCACert(value, cache) {
|
|
@@ -433,7 +431,7 @@ class Request extends module_1.default {
|
|
|
433
431
|
if (this.isURL(value)) {
|
|
434
432
|
return value;
|
|
435
433
|
}
|
|
436
|
-
const auth = host_1.
|
|
434
|
+
const auth = host_1.formatBasicAuth(url);
|
|
437
435
|
return url.protocol + '//' + (auth && (auth + '@')) + url.hostname + (url.port ? ':' + url.port : '') + (value.startsWith('/') ? '' : '/') + value;
|
|
438
436
|
}
|
|
439
437
|
static fromStatusCode(value) {
|
|
@@ -745,19 +743,19 @@ class Request extends module_1.default {
|
|
|
745
743
|
const width = count.toString().length;
|
|
746
744
|
output.forEach(item => {
|
|
747
745
|
const [title, origin, downloads, messages] = item;
|
|
748
|
-
const options = { ...title === 'HTTP1' ? module_1.
|
|
746
|
+
const options = { ...title === 'HTTP1' ? module_1.LOG_STYLE_NOTICE : module_1.LOG_STYLE_INFO };
|
|
749
747
|
if (messages.length === 1) {
|
|
750
748
|
const message = messages[0];
|
|
751
749
|
message[1] = title;
|
|
752
750
|
message[2] = [origin + message[2][0], message[2][1]];
|
|
753
751
|
message[4] = Object.assign(message[4], options);
|
|
754
|
-
module_1.
|
|
752
|
+
module_1.formatMessage(...message);
|
|
755
753
|
}
|
|
756
754
|
else {
|
|
757
755
|
this.formatMessage(1024, title, [origin, 'downloads: ' + downloads.toString().padStart(width)], '', options);
|
|
758
756
|
messages.forEach(args => {
|
|
759
757
|
args[4].titleIndent = true;
|
|
760
|
-
module_1.
|
|
758
|
+
module_1.formatMessage(...args);
|
|
761
759
|
});
|
|
762
760
|
}
|
|
763
761
|
});
|
|
@@ -784,7 +782,7 @@ class Request extends module_1.default {
|
|
|
784
782
|
}
|
|
785
783
|
init(config) {
|
|
786
784
|
if (config) {
|
|
787
|
-
const { headers, httpVersion, ipVersion,
|
|
785
|
+
const { headers, httpVersion, ipVersion, readTimeout } = config;
|
|
788
786
|
if ((0, types_1.isObject)(headers)) {
|
|
789
787
|
setOutgoingHeaders(this[kHeaders] || (this[kHeaders] = {}), headers);
|
|
790
788
|
}
|
|
@@ -819,7 +817,7 @@ class Request extends module_1.default {
|
|
|
819
817
|
this._config.retryWait = Math.min(retryWait, 600 * 1000);
|
|
820
818
|
}
|
|
821
819
|
if (retryAfter >= 0) {
|
|
822
|
-
this._config.retryAfter = Math.min(retryAfter, module_1.
|
|
820
|
+
this._config.retryAfter = Math.min(retryAfter, module_1.MAX_TIMEOUT);
|
|
823
821
|
}
|
|
824
822
|
if (retryLimit >= 0) {
|
|
825
823
|
this._config.retryLimit = retryLimit;
|
|
@@ -995,7 +993,7 @@ class Request extends module_1.default {
|
|
|
995
993
|
if (!ARIA2.BIN) {
|
|
996
994
|
return Promise.reject((0, types_1.errorMessage)("aria2", "Binary not found"));
|
|
997
995
|
}
|
|
998
|
-
if (typeof uri === 'string' && module_1.
|
|
996
|
+
if (typeof uri === 'string' && module_1.isURL(uri)) {
|
|
999
997
|
try {
|
|
1000
998
|
uri = new URL(uri);
|
|
1001
999
|
}
|
|
@@ -1014,7 +1012,7 @@ class Request extends module_1.default {
|
|
|
1014
1012
|
let next = false;
|
|
1015
1013
|
binOpts = binOpts.filter(opt => !((0, types_1.isString)(opt) && /^-[a-z][\S\s]*$/i.test(opt.trim()))).map((opt) => {
|
|
1016
1014
|
if (next) {
|
|
1017
|
-
if (!module_1.
|
|
1015
|
+
if (!module_1.asString(opt).startsWith('--')) {
|
|
1018
1016
|
return [];
|
|
1019
1017
|
}
|
|
1020
1018
|
next = false;
|
|
@@ -1036,12 +1034,12 @@ class Request extends module_1.default {
|
|
|
1036
1034
|
}
|
|
1037
1035
|
break;
|
|
1038
1036
|
default:
|
|
1039
|
-
return match[3] ? [match[1], module_1.
|
|
1037
|
+
return match[3] ? [match[1], module_1.sanitizeArgs(match[3])] : [match[1]];
|
|
1040
1038
|
}
|
|
1041
1039
|
}
|
|
1042
1040
|
}
|
|
1043
1041
|
else if (value) {
|
|
1044
|
-
return [module_1.
|
|
1042
|
+
return [module_1.sanitizeArgs(value)];
|
|
1045
1043
|
}
|
|
1046
1044
|
break;
|
|
1047
1045
|
}
|
|
@@ -1050,7 +1048,7 @@ class Request extends module_1.default {
|
|
|
1050
1048
|
return [opt.toString()];
|
|
1051
1049
|
default:
|
|
1052
1050
|
if ((0, types_1.isArray)(opt)) {
|
|
1053
|
-
return opt.filter(item => (0, types_1.isString)(item)).map((item) => module_1.
|
|
1051
|
+
return opt.filter(item => (0, types_1.isString)(item)).map((item) => module_1.sanitizeArgs(item));
|
|
1054
1052
|
}
|
|
1055
1053
|
break;
|
|
1056
1054
|
}
|
|
@@ -1059,7 +1057,7 @@ class Request extends module_1.default {
|
|
|
1059
1057
|
}
|
|
1060
1058
|
}
|
|
1061
1059
|
}
|
|
1062
|
-
if (!
|
|
1060
|
+
if (!pathname) {
|
|
1063
1061
|
if (this.host) {
|
|
1064
1062
|
return Promise.reject((0, types_1.errorMessage)("aria2", "Invalid parameters", 'pathname'));
|
|
1065
1063
|
}
|
|
@@ -1068,7 +1066,7 @@ class Request extends module_1.default {
|
|
|
1068
1066
|
if ((this.host || this.hasOwnPermission()) && !this.canWrite(pathname = path.resolve(pathname.trim()))) {
|
|
1069
1067
|
return Promise.reject((0, types_1.errorMessage)("aria2", "Unsupported access", pathname));
|
|
1070
1068
|
}
|
|
1071
|
-
if (!module_1.
|
|
1069
|
+
if (!module_1.createDir(pathname)) {
|
|
1072
1070
|
return Promise.reject((0, types_1.errorMessage)("aria2", "Path is not a directory", pathname));
|
|
1073
1071
|
}
|
|
1074
1072
|
silent ?? (silent = this[kSingleton]);
|
|
@@ -1179,7 +1177,7 @@ class Request extends module_1.default {
|
|
|
1179
1177
|
}
|
|
1180
1178
|
}
|
|
1181
1179
|
if (origin) {
|
|
1182
|
-
const secure = this[kCerts]?.[1][origin] ||
|
|
1180
|
+
const secure = this[kCerts]?.[1][origin] || this.host && TLS.FILE[origin];
|
|
1183
1181
|
if (secure) {
|
|
1184
1182
|
if (secure.ca && ignoreOpt('--ca-certificate')) {
|
|
1185
1183
|
args.push(`--ca-certificate="${escapeQuote(secure.ca)}"`);
|
|
@@ -1234,8 +1232,8 @@ class Request extends module_1.default {
|
|
|
1234
1232
|
args = binOpts.concat(args);
|
|
1235
1233
|
}
|
|
1236
1234
|
if (args.length) {
|
|
1237
|
-
if (module_1.
|
|
1238
|
-
this.formatMessage(32768, 'ARIA2', ARIA2.BIN, args.join(' '), { ...module_1.
|
|
1235
|
+
if (module_1.hasLogType(32768)) {
|
|
1236
|
+
this.formatMessage(32768, 'ARIA2', ARIA2.BIN, args.join(' '), { ...module_1.LOG_STYLE_WARN });
|
|
1239
1237
|
}
|
|
1240
1238
|
else {
|
|
1241
1239
|
this.addLog(types_1.STATUS_TYPE.INFO, path.basename(ARIA2.BIN) + ' ' + args.join(' '), "aria2");
|
|
@@ -1250,7 +1248,7 @@ class Request extends module_1.default {
|
|
|
1250
1248
|
closeTorrent(pid);
|
|
1251
1249
|
reject(err);
|
|
1252
1250
|
};
|
|
1253
|
-
const { pid, stdout, stderr } = child_process.spawn(module_1.
|
|
1251
|
+
const { pid, stdout, stderr } = child_process.spawn(module_1.sanitizeCmd(ARIA2.BIN), args, { cwd: pathname, shell: true, signal: this.signal, uid: ARIA2.EXEC_UID, gid: ARIA2.EXEC_GID })
|
|
1254
1252
|
.on('exit', code => {
|
|
1255
1253
|
closeTorrent(pid);
|
|
1256
1254
|
if (aborted) {
|
|
@@ -1260,15 +1258,15 @@ class Request extends module_1.default {
|
|
|
1260
1258
|
errorResponse(pid, (0, types_1.createAbortError)());
|
|
1261
1259
|
return;
|
|
1262
1260
|
}
|
|
1263
|
-
if (
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1261
|
+
if (code) {
|
|
1262
|
+
reject((0, types_1.errorValue)(message || "Unknown", 'Exit status: ' + code));
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1265
|
+
const currentTime = Date.now();
|
|
1266
|
+
const result = [];
|
|
1267
|
+
let messageUnit;
|
|
1268
|
+
for (const match of out.matchAll(/\|(OK|ERR|INPR)\s*\|\s*([^|]+)\|\s*(\d+)\|([^\n]+)/g)) {
|
|
1269
|
+
if (!match[4].startsWith('[MEMORY]')) {
|
|
1272
1270
|
const file = path.normalize(match[4].trim());
|
|
1273
1271
|
switch (match[1]) {
|
|
1274
1272
|
case 'OK':
|
|
@@ -1286,20 +1284,17 @@ class Request extends module_1.default {
|
|
|
1286
1284
|
break;
|
|
1287
1285
|
}
|
|
1288
1286
|
}
|
|
1289
|
-
if (result.length && !silent && LOG_HTTP && LOG_TIMEPROCESS) {
|
|
1290
|
-
this.writeTimeProcess("aria2", uri, startTime, { type: 1024, queue: true, messageUnit, messageUnitMinWidth: 9, bypassLog: true });
|
|
1291
|
-
}
|
|
1292
|
-
this.addLog(result.length ? types_1.STATUS_TYPE.INFO : types_1.STATUS_TYPE.ERROR, out, currentTime, currentTime - startTime, "aria2", uri);
|
|
1293
|
-
resolve(result);
|
|
1294
1287
|
}
|
|
1295
|
-
|
|
1296
|
-
|
|
1288
|
+
if (result.length && !silent && LOG_HTTP && LOG_TIMEPROCESS) {
|
|
1289
|
+
this.writeTimeProcess("aria2", uri, startTime, { type: 1024, queue: true, messageUnit, messageUnitMinWidth: 9, bypassLog: true });
|
|
1297
1290
|
}
|
|
1291
|
+
this.addLog(result.length ? types_1.STATUS_TYPE.INFO : types_1.STATUS_TYPE.ERROR, out, currentTime, currentTime - startTime, "aria2", uri);
|
|
1292
|
+
resolve(result);
|
|
1298
1293
|
})
|
|
1299
1294
|
.on('error', err => errorResponse(pid, err));
|
|
1300
1295
|
stdout.setEncoding('utf-8').on('data', (value) => out += value);
|
|
1301
1296
|
stderr.setEncoding('utf-8').on('data', (value) => message += value);
|
|
1302
|
-
if (pid !== undefined && module_1.
|
|
1297
|
+
if (pid !== undefined && module_1.isFile(uri, 'torrent')) {
|
|
1303
1298
|
if (!ARIA2.PID_TIMER) {
|
|
1304
1299
|
const clearTimer = () => {
|
|
1305
1300
|
clearInterval(ARIA2.PID_TIMER);
|
|
@@ -1320,24 +1315,22 @@ class Request extends module_1.default {
|
|
|
1320
1315
|
}
|
|
1321
1316
|
if (ARIA2.UPDATE_STATUS && !silent) {
|
|
1322
1317
|
const item = ARIA2.PID_QUEUE.shift();
|
|
1323
|
-
if (item) {
|
|
1324
|
-
const broadcastId = item[2];
|
|
1325
|
-
if (!ARIA2.UPDATE_BROADCAST_ONLY || broadcastId) {
|
|
1326
|
-
let progressBar;
|
|
1327
|
-
if (item[2]) {
|
|
1328
|
-
progressBar = true;
|
|
1329
|
-
}
|
|
1330
|
-
else {
|
|
1331
|
-
const current = (0, types_1.getLogCurrent)();
|
|
1332
|
-
progressBar = current?.type === 128 && current.title === "aria2";
|
|
1333
|
-
}
|
|
1334
|
-
this.formatMessage(128, "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 });
|
|
1335
|
-
}
|
|
1336
|
-
ARIA2.PID_QUEUE.push(item);
|
|
1337
|
-
}
|
|
1338
|
-
else {
|
|
1318
|
+
if (!item) {
|
|
1339
1319
|
clearTimer();
|
|
1320
|
+
return;
|
|
1340
1321
|
}
|
|
1322
|
+
if ((!ARIA2.UPDATE_BROADCAST_ONLY || item[2]) && this.host?.logState !== 0) {
|
|
1323
|
+
let progressBar;
|
|
1324
|
+
if (item[2]) {
|
|
1325
|
+
progressBar = true;
|
|
1326
|
+
}
|
|
1327
|
+
else {
|
|
1328
|
+
const current = (0, types_1.getLogCurrent)();
|
|
1329
|
+
progressBar = current?.type === 128 && current.title === "aria2";
|
|
1330
|
+
}
|
|
1331
|
+
this.formatMessage(128, "aria2", ['Downloading...', (0, types_1.formatTime)(startTime, true)], (PLATFORM_WIN32 ? 'taskkill /f /pid' : 'kill') + ` ${item[0]} -> ` + item[1], { ...module_1.LOG_STYLE_INFO, progressBar, broadcastId: item[2] });
|
|
1332
|
+
}
|
|
1333
|
+
ARIA2.PID_QUEUE.push(item);
|
|
1341
1334
|
}
|
|
1342
1335
|
}, (ARIA2.UPDATE_STATUS || 30) * 1000);
|
|
1343
1336
|
}
|
|
@@ -1360,16 +1353,16 @@ class Request extends module_1.default {
|
|
|
1360
1353
|
}
|
|
1361
1354
|
let host;
|
|
1362
1355
|
if (this.host) {
|
|
1363
|
-
host = (_o = HTTP.HOST)[_p = url.origin] || (_o[_p] = new host_1
|
|
1356
|
+
host = (_o = HTTP.HOST)[_p = url.origin] || (_o[_p] = new host_1(url, HTTP.VERSION));
|
|
1364
1357
|
}
|
|
1365
1358
|
else {
|
|
1366
|
-
host = (_q = this[kHostInfo])[_r = url.origin] || (_q[_r] = new host_1
|
|
1359
|
+
host = (_q = this[kHostInfo])[_r = url.origin] || (_q[_r] = new host_1(url, this.httpVersion || 1));
|
|
1367
1360
|
}
|
|
1368
1361
|
return { ...options, host, url };
|
|
1369
1362
|
}
|
|
1370
1363
|
open(uri, options) {
|
|
1371
1364
|
var _o, _p;
|
|
1372
|
-
let { host, url, httpVersion, method = 'GET', encoding, format, headers, postData, keepAlive, agentTimeout, socketPath, timeout = this._config.connectTimeout, outStream } = options;
|
|
1365
|
+
let { host, url, httpVersion, method = 'GET', search, encoding, format, headers, postData, keepAlive, agentTimeout, socketPath, timeout = this._config.connectTimeout, outStream } = options;
|
|
1373
1366
|
const getting = method === 'GET';
|
|
1374
1367
|
const posting = method === 'POST';
|
|
1375
1368
|
if (format) {
|
|
@@ -1416,6 +1409,12 @@ class Request extends module_1.default {
|
|
|
1416
1409
|
url = new URL(uri);
|
|
1417
1410
|
options.url = url;
|
|
1418
1411
|
}
|
|
1412
|
+
if (search) {
|
|
1413
|
+
for (const param in search) {
|
|
1414
|
+
url.searchParams.append(param, search[param]);
|
|
1415
|
+
}
|
|
1416
|
+
uri = url.href;
|
|
1417
|
+
}
|
|
1419
1418
|
const checkEncoding = (response, statusCode, contentEncoding = '') => {
|
|
1420
1419
|
switch (statusCode) {
|
|
1421
1420
|
case 206:
|
|
@@ -1463,13 +1462,13 @@ class Request extends module_1.default {
|
|
|
1463
1462
|
(_o = (headers || (headers = {})))['accept-encoding'] || (_o['accept-encoding'] = 'gzip, deflate, br' + (LIB_ZSTD ? ', zstd' : ''));
|
|
1464
1463
|
}
|
|
1465
1464
|
if (secure) {
|
|
1466
|
-
const certs = this[kCerts]?.[0][origin] ||
|
|
1465
|
+
const certs = this[kCerts]?.[0][origin] || this.host && TLS.TEXT[origin];
|
|
1467
1466
|
if (certs) {
|
|
1468
1467
|
({ ca, cert, key, version: minVersion } = certs);
|
|
1469
1468
|
}
|
|
1470
1469
|
}
|
|
1471
1470
|
if (!proxy && httpVersion !== 1 && ((httpVersion || host.version) === 2 && version !== 1 || secure && version === 2 && host.failed(2, true) === 0)) {
|
|
1472
|
-
request = ((_p = this[kSession][0])[origin] || (_p[origin] = http2.connect(origin, { lookup: this.lookupDns(hostname), ca, cert, key, minVersion, settings: localhost ? { maxFrameSize: 16777215, enablePush: false } : { enablePush: false } }))).request({ ...baseHeaders, ...host_1.
|
|
1471
|
+
request = ((_p = this[kSession][0])[origin] || (_p[origin] = http2.connect(origin, { lookup: this.lookupDns(hostname), ca, cert, key, minVersion, settings: localhost ? { maxFrameSize: 16777215, enablePush: false } : { enablePush: false } }))).request({ ...baseHeaders, ...host_1.getBasicAuth(url), ...headers, ':path': pathname, ':method': method });
|
|
1473
1472
|
if (getting) {
|
|
1474
1473
|
const listenerMap = {};
|
|
1475
1474
|
const onEvent = request.on.bind(request);
|
|
@@ -1579,7 +1578,7 @@ class Request extends module_1.default {
|
|
|
1579
1578
|
}
|
|
1580
1579
|
}
|
|
1581
1580
|
}
|
|
1582
|
-
const basicAuth = host_1.
|
|
1581
|
+
const basicAuth = host_1.getBasicAuth(url);
|
|
1583
1582
|
if (baseHeaders || basicAuth) {
|
|
1584
1583
|
headers = { ...baseHeaders, ...basicAuth, ...headers };
|
|
1585
1584
|
}
|
|
@@ -1735,7 +1734,7 @@ class Request extends module_1.default {
|
|
|
1735
1734
|
};
|
|
1736
1735
|
const addValue = (name, value) => {
|
|
1737
1736
|
if (value !== undefined) {
|
|
1738
|
-
const disposition = createPart(name) + module_1.
|
|
1737
|
+
const disposition = createPart(name) + module_1.asString(value) + "\r\n";
|
|
1739
1738
|
write.append(disposition);
|
|
1740
1739
|
contentLength += Buffer.byteLength(disposition);
|
|
1741
1740
|
}
|
|
@@ -1754,7 +1753,7 @@ class Request extends module_1.default {
|
|
|
1754
1753
|
try {
|
|
1755
1754
|
if (typeof target === 'string') {
|
|
1756
1755
|
filename || (filename = path.basename(target));
|
|
1757
|
-
type || (type = module_1.
|
|
1756
|
+
type || (type = module_1.lookupMime(filename));
|
|
1758
1757
|
target = fs.readFileSync(target);
|
|
1759
1758
|
}
|
|
1760
1759
|
else if (target instanceof stream.Readable) {
|
|
@@ -1768,14 +1767,14 @@ class Request extends module_1.default {
|
|
|
1768
1767
|
throw (0, types_1.errorMessage)('File', "Unknown", "multipart/form-data");
|
|
1769
1768
|
}
|
|
1770
1769
|
if (!type || !filename) {
|
|
1771
|
-
const result = await module_1.
|
|
1770
|
+
const result = await module_1.resolveMime(target);
|
|
1772
1771
|
let ext;
|
|
1773
1772
|
if (result) {
|
|
1774
1773
|
type || (type = result.mime);
|
|
1775
1774
|
ext = result.ext;
|
|
1776
1775
|
}
|
|
1777
1776
|
else if (type) {
|
|
1778
|
-
ext = module_1.
|
|
1777
|
+
ext = module_1.lookupMime(type, true);
|
|
1779
1778
|
}
|
|
1780
1779
|
if (ext && !filename) {
|
|
1781
1780
|
filename = (0, types_1.generateUUID)() + '.' + ext;
|
|
@@ -1803,7 +1802,7 @@ class Request extends module_1.default {
|
|
|
1803
1802
|
}
|
|
1804
1803
|
}
|
|
1805
1804
|
if (!valid) {
|
|
1806
|
-
return Promise.reject((0, types_1.errorValue)(
|
|
1805
|
+
return Promise.reject((0, types_1.errorValue)("No files were attached", "multipart/form-data"));
|
|
1807
1806
|
}
|
|
1808
1807
|
}
|
|
1809
1808
|
else {
|
|
@@ -1811,7 +1810,7 @@ class Request extends module_1.default {
|
|
|
1811
1810
|
contentType = 'application/' + contentType.trim();
|
|
1812
1811
|
}
|
|
1813
1812
|
if (!(0, types_1.isPlainObject)(data)) {
|
|
1814
|
-
data = module_1.
|
|
1813
|
+
data = module_1.asString(data);
|
|
1815
1814
|
}
|
|
1816
1815
|
else if (contentType === "application/x-www-form-urlencoded") {
|
|
1817
1816
|
data = qs.stringify(data);
|
|
@@ -1842,7 +1841,7 @@ class Request extends module_1.default {
|
|
|
1842
1841
|
if (!closed) {
|
|
1843
1842
|
closed = true;
|
|
1844
1843
|
if (outStream && (0, types_1.isString)(pipeTo)) {
|
|
1845
|
-
(0,
|
|
1844
|
+
(0, util_1.cleanupStream)(outStream, pipeTo);
|
|
1846
1845
|
}
|
|
1847
1846
|
reject(typeof err === 'string' ? new Error(err) : err);
|
|
1848
1847
|
}
|
|
@@ -1859,10 +1858,10 @@ class Request extends module_1.default {
|
|
|
1859
1858
|
try {
|
|
1860
1859
|
const request = this.opts(href, opts);
|
|
1861
1860
|
if (outStream && (0, types_1.isString)(pipeTo)) {
|
|
1862
|
-
(0,
|
|
1861
|
+
(0, util_1.cleanupStream)(outStream, pipeTo);
|
|
1863
1862
|
}
|
|
1864
1863
|
if (pipeTo) {
|
|
1865
|
-
if (
|
|
1864
|
+
if (typeof pipeTo === 'string') {
|
|
1866
1865
|
outStream = fs.createWriteStream(pipeTo, { emitClose: false, highWaterMark: request.host.localhost ? 65536 : 4096 });
|
|
1867
1866
|
request.outStream = outStream;
|
|
1868
1867
|
}
|
|
@@ -1874,7 +1873,7 @@ class Request extends module_1.default {
|
|
|
1874
1873
|
request.httpVersion = httpVersion;
|
|
1875
1874
|
}
|
|
1876
1875
|
const client = this.open(href, request);
|
|
1877
|
-
const { host, url, encoding, outFormat } = request;
|
|
1876
|
+
const { host, url, encoding, progressId, outFormat } = request;
|
|
1878
1877
|
let buffer, aborted;
|
|
1879
1878
|
({ httpVersion, outAbort } = request);
|
|
1880
1879
|
const isAborted = () => client.destroyed || httpVersion === 2 && client.aborted;
|
|
@@ -1915,9 +1914,11 @@ class Request extends module_1.default {
|
|
|
1915
1914
|
const buffering = request.connected?.call(client, headers);
|
|
1916
1915
|
const pipeline = pipeTo ? !(0, types_1.isString)(pipeTo) : false;
|
|
1917
1916
|
const enabled = buffering !== false && !pipeline;
|
|
1918
|
-
const
|
|
1919
|
-
|
|
1920
|
-
|
|
1917
|
+
const maxBufferSize = request.maxBufferSize ? (0, types_1.alignSize)(request.maxBufferSize) : 0;
|
|
1918
|
+
const { host: parent, readTimeout } = this;
|
|
1919
|
+
const contentLength = parent && progressId !== undefined ? parseInt(headers['content-length'] || '0') : 0;
|
|
1920
|
+
let dataLength = 0, mibsTime, delayTime;
|
|
1921
|
+
if (log || readTimeout > 0 || contentLength > 0) {
|
|
1921
1922
|
client.once('readable', () => {
|
|
1922
1923
|
if (readTimeout > 0) {
|
|
1923
1924
|
timeout = setTimeout(() => {
|
|
@@ -1934,7 +1935,10 @@ class Request extends module_1.default {
|
|
|
1934
1935
|
delayTime = Date.now() - this.startTime;
|
|
1935
1936
|
break;
|
|
1936
1937
|
}
|
|
1937
|
-
|
|
1938
|
+
}
|
|
1939
|
+
mibsTime = process.hrtime();
|
|
1940
|
+
if (contentLength > 0) {
|
|
1941
|
+
parent.updateProgress("request", progressId, 0, 0, mibsTime);
|
|
1938
1942
|
}
|
|
1939
1943
|
});
|
|
1940
1944
|
}
|
|
@@ -1954,6 +1958,19 @@ class Request extends module_1.default {
|
|
|
1954
1958
|
else {
|
|
1955
1959
|
buffer = typeof chunk === 'string' ? chunk : [chunk];
|
|
1956
1960
|
}
|
|
1961
|
+
if (contentLength > 0) {
|
|
1962
|
+
dataLength += Buffer.byteLength(chunk, encoding);
|
|
1963
|
+
parent.updateProgress("request", progressId, dataLength, contentLength);
|
|
1964
|
+
}
|
|
1965
|
+
if (maxBufferSize > 0) {
|
|
1966
|
+
if (contentLength === 0) {
|
|
1967
|
+
dataLength += Buffer.byteLength(chunk, encoding);
|
|
1968
|
+
}
|
|
1969
|
+
if (dataLength > maxBufferSize) {
|
|
1970
|
+
abortResponse();
|
|
1971
|
+
throwError((0, types_1.errorValue)("Size limit was exceeded", href.toString()));
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1957
1974
|
});
|
|
1958
1975
|
}
|
|
1959
1976
|
client.once('end', () => {
|
|
@@ -1976,20 +1993,15 @@ class Request extends module_1.default {
|
|
|
1976
1993
|
buffer = buffer.toString(encoding);
|
|
1977
1994
|
}
|
|
1978
1995
|
}
|
|
1996
|
+
dataLength = Buffer.byteLength(buffer, encoding);
|
|
1979
1997
|
if (mibsTime) {
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
else if (unit < 1000) {
|
|
1985
|
-
messageUnit = unit.toPrecision(3) + 'MiB/s';
|
|
1986
|
-
}
|
|
1987
|
-
else {
|
|
1988
|
-
messageUnit = (unit / 1000).toPrecision(3) + 'GiB/s';
|
|
1989
|
-
}
|
|
1998
|
+
messageUnit = (0, util_1.getTransferRate)(dataLength, (0, types_1.convertTime)(process.hrtime(mibsTime), false) * 1000);
|
|
1999
|
+
}
|
|
2000
|
+
if (contentLength > 0) {
|
|
2001
|
+
parent.updateProgress("request", progressId, dataLength, dataLength);
|
|
1990
2002
|
}
|
|
1991
2003
|
if (typeof buffer === 'string') {
|
|
1992
|
-
if (buffer.startsWith('\uFEFF') && encoding !== 'utf16le') {
|
|
2004
|
+
if (buffer.startsWith('\uFEFF') && encoding !== 'utf16le' && encoding !== 'utf-16le') {
|
|
1993
2005
|
buffer = buffer.substring(1);
|
|
1994
2006
|
}
|
|
1995
2007
|
if (outFormat) {
|
|
@@ -2029,11 +2041,14 @@ class Request extends module_1.default {
|
|
|
2029
2041
|
result = buffer;
|
|
2030
2042
|
}
|
|
2031
2043
|
}
|
|
2032
|
-
else if (enabled && this.readExpect === 'always') {
|
|
2033
|
-
throwError('No data received');
|
|
2034
|
-
return;
|
|
2035
|
-
}
|
|
2036
2044
|
else {
|
|
2045
|
+
if (contentLength > 0) {
|
|
2046
|
+
parent.updateProgress("request", progressId, 0, contentLength);
|
|
2047
|
+
}
|
|
2048
|
+
if (enabled && this.readExpect === 'always') {
|
|
2049
|
+
throwError('No data received');
|
|
2050
|
+
return;
|
|
2051
|
+
}
|
|
2037
2052
|
result = encoding && !pipeline ? '' : null;
|
|
2038
2053
|
titleBgColor = 'bgBlue';
|
|
2039
2054
|
}
|
|
@@ -2047,7 +2062,10 @@ class Request extends module_1.default {
|
|
|
2047
2062
|
const redirectResponse = (statusCode, location) => {
|
|
2048
2063
|
abortResponse();
|
|
2049
2064
|
if (location) {
|
|
2050
|
-
if (
|
|
2065
|
+
if (request.follow_redirect === false) {
|
|
2066
|
+
throwError(formatStatus(statusCode, 'Follow redirect was disabled'));
|
|
2067
|
+
}
|
|
2068
|
+
else if (++redirects <= this._config.redirectLimit) {
|
|
2051
2069
|
downloadUri.call(this, Request.fromURL(url, location));
|
|
2052
2070
|
}
|
|
2053
2071
|
else {
|
|
@@ -2353,9 +2371,5 @@ class Request extends module_1.default {
|
|
|
2353
2371
|
}
|
|
2354
2372
|
}
|
|
2355
2373
|
_a = kSingleton, _b = kHttpVersion, _c = kHeaders, _d = kCerts, _e = kConnectDns, _f = kPendingDns, _g = kConnectHttp, _h = kStatusOn, _j = kHeadersOn, _k = kDownloading, _l = kHostInfo, _m = kSession;
|
|
2356
|
-
exports.default = Request;
|
|
2357
2374
|
|
|
2358
|
-
|
|
2359
|
-
module.exports = exports.default;
|
|
2360
|
-
module.exports.default = exports.default;
|
|
2361
|
-
}
|
|
2375
|
+
module.exports = Request;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e-mc/request",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Request constructor for E-mc.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -20,11 +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.
|
|
24
|
-
"@e-mc/types": "0.
|
|
23
|
+
"@e-mc/module": "0.9.0",
|
|
24
|
+
"@e-mc/types": "0.9.0",
|
|
25
25
|
"combined-stream": "^1.0.8",
|
|
26
26
|
"js-yaml": "^4.1.0",
|
|
27
|
-
"picomatch": "^
|
|
27
|
+
"picomatch": "^4.0.2",
|
|
28
28
|
"which": "^2.0.2"
|
|
29
29
|
}
|
|
30
30
|
}
|
package/util.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import type { AuthValue } from '../types/lib/http';
|
|
2
|
+
|
|
1
3
|
import type { IncomingHttpHeaders, OutgoingHttpHeaders } from 'http';
|
|
4
|
+
import type { Readable, Writable } from 'stream';
|
|
2
5
|
|
|
3
6
|
declare namespace util {
|
|
4
7
|
function parseHeader<T = unknown>(headers: IncomingHttpHeaders, name: string): T | undefined;
|
|
@@ -12,6 +15,12 @@ declare namespace util {
|
|
|
12
15
|
function asInt(value: unknown): number;
|
|
13
16
|
function asFloat(value: unknown): number;
|
|
14
17
|
function fromSeconds(value: unknown): number;
|
|
18
|
+
function getTransferRate(length: number, timeMs: number, unitSeparator?: string): string;
|
|
19
|
+
function hasSameStat(src: string, dest: string, keepEmpty?: boolean): boolean;
|
|
20
|
+
function hasSize(value: string, keepEmpty?: boolean): boolean;
|
|
21
|
+
function getSize(value: string, diskUsed?: boolean): number;
|
|
22
|
+
function byteLength(value: Bufferable, encoding?: BufferEncoding): number;
|
|
23
|
+
function cleanupStream(target: Readable | Writable, pathname?: string): void;
|
|
15
24
|
}
|
|
16
25
|
|
|
17
26
|
export = util;
|
package/util.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
exports.cleanupStream = exports.byteLength = exports.hasSameStat = exports.getSize = exports.hasSize = exports.getTransferRate = exports.fromSeconds = exports.asFloat = exports.asInt = exports.trimPath = exports.isRetryable = exports.checkRetryable = exports.hasBasicAuth = exports.getBasicAuth = exports.normalizeHeaders = exports.parseHeader = void 0;
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const fs = require("fs");
|
|
4
5
|
const module_1 = require("@e-mc/module");
|
|
5
6
|
const types_1 = require("@e-mc/types");
|
|
6
7
|
const safeInt = (value) => value >= 0 ? Math.min(value, Number.MAX_SAFE_INTEGER) : NaN;
|
|
@@ -9,9 +10,8 @@ function parseHeader(headers, name) {
|
|
|
9
10
|
if (value) {
|
|
10
11
|
switch (name.toLowerCase()) {
|
|
11
12
|
case 'content-disposition': {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
while (match = pattern.exec(value)) {
|
|
13
|
+
let result;
|
|
14
|
+
for (const match of value.matchAll(/\bfilename(?:\*\s*=\s*UTF-8''([^\s;]+)|\s*=\s*(?:"([^"]+)"|([^\s;]+)))/gi)) {
|
|
15
15
|
if (match[1]) {
|
|
16
16
|
return decodeURIComponent(match[1]).trim();
|
|
17
17
|
}
|
|
@@ -36,7 +36,7 @@ function normalizeHeaders(headers) {
|
|
|
36
36
|
break;
|
|
37
37
|
default:
|
|
38
38
|
if (Array.isArray(value)) {
|
|
39
|
-
value = value.map(out => module_1.
|
|
39
|
+
value = value.map(out => module_1.asString(out).trim());
|
|
40
40
|
break;
|
|
41
41
|
}
|
|
42
42
|
continue;
|
|
@@ -57,7 +57,7 @@ function getBasicAuth(username, password) {
|
|
|
57
57
|
exports.getBasicAuth = getBasicAuth;
|
|
58
58
|
function hasBasicAuth(value) {
|
|
59
59
|
try {
|
|
60
|
-
return
|
|
60
|
+
return new URL(value).username.length > 0;
|
|
61
61
|
}
|
|
62
62
|
catch {
|
|
63
63
|
}
|
|
@@ -146,3 +146,75 @@ function fromSeconds(value) {
|
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
exports.fromSeconds = fromSeconds;
|
|
149
|
+
function getTransferRate(length, timeMs, unitSeparator = '') {
|
|
150
|
+
const unit = (length * 8) / timeMs;
|
|
151
|
+
if (unit < 1) {
|
|
152
|
+
return Math.ceil(unit * 1000) + unitSeparator + 'KiB/s';
|
|
153
|
+
}
|
|
154
|
+
if (unit < 1000) {
|
|
155
|
+
return unit.toPrecision(3) + unitSeparator + 'MiB/s';
|
|
156
|
+
}
|
|
157
|
+
return (unit / 1000).toPrecision(3) + unitSeparator + 'GiB/s';
|
|
158
|
+
}
|
|
159
|
+
exports.getTransferRate = getTransferRate;
|
|
160
|
+
function hasSize(value, keepEmpty) {
|
|
161
|
+
try {
|
|
162
|
+
const statSrc = fs.statSync(value);
|
|
163
|
+
if (statSrc.size > 0) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
if (!keepEmpty) {
|
|
167
|
+
fs.unlinkSync(value);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
exports.hasSize = hasSize;
|
|
175
|
+
function getSize(value, diskUsed) {
|
|
176
|
+
try {
|
|
177
|
+
return (diskUsed ? fs.lstatSync(value) : fs.statSync(value)).size;
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.getSize = getSize;
|
|
184
|
+
function hasSameStat(src, dest, keepEmpty) {
|
|
185
|
+
try {
|
|
186
|
+
if (fs.existsSync(dest)) {
|
|
187
|
+
const { size, mtimeMs } = fs.statSync(src);
|
|
188
|
+
if (size > 0) {
|
|
189
|
+
const statDest = fs.statSync(dest);
|
|
190
|
+
return size === statDest.size && mtimeMs === statDest.mtimeMs;
|
|
191
|
+
}
|
|
192
|
+
if (!keepEmpty) {
|
|
193
|
+
fs.unlinkSync(src);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
}
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
exports.hasSameStat = hasSameStat;
|
|
202
|
+
function byteLength(value, encoding) {
|
|
203
|
+
return typeof value === 'string' && (path.isAbsolute(value) || module_1.isPath(value)) ? getSize(value) : Buffer.byteLength(value, encoding && (0, types_1.getEncoding)(encoding));
|
|
204
|
+
}
|
|
205
|
+
exports.byteLength = byteLength;
|
|
206
|
+
function cleanupStream(stream, uri) {
|
|
207
|
+
try {
|
|
208
|
+
stream.removeAllListeners();
|
|
209
|
+
stream.destroy();
|
|
210
|
+
if (uri && fs.existsSync(uri)) {
|
|
211
|
+
fs.unlinkSync(uri);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
if (!module_1.isErrorCode(err, 'ENOENT')) {
|
|
216
|
+
module_1.writeFail(["Unable to delete file", path.basename(uri)], err, 32);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
exports.cleanupStream = cleanupStream;
|