@e-mc/request 0.13.6 → 0.13.7
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 +4 -4
- package/http/adapter/index.js +6 -1
- package/http/host/altsvc/index.js +92 -0
- package/http/host/index.js +66 -113
- package/index.js +143 -142
- package/package.json +3 -3
- package/util.d.ts +3 -3
- package/util.js +41 -21
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
## Interface
|
|
11
11
|
|
|
12
|
-
* [View Source](https://www.unpkg.com/@e-mc/types@0.13.
|
|
12
|
+
* [View Source](https://www.unpkg.com/@e-mc/types@0.13.7/lib/index.d.ts)
|
|
13
13
|
|
|
14
14
|
```typescript
|
|
15
15
|
import type { IModule, ModuleConstructor } from "./index";
|
|
@@ -252,9 +252,9 @@ instance.get("http://hostname/path/config.yml", options).then(data => {
|
|
|
252
252
|
|
|
253
253
|
## References
|
|
254
254
|
|
|
255
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
256
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
257
|
-
- https://www.unpkg.com/@e-mc/types@0.13.
|
|
255
|
+
- https://www.unpkg.com/@e-mc/types@0.13.7/lib/http.d.ts
|
|
256
|
+
- https://www.unpkg.com/@e-mc/types@0.13.7/lib/request.d.ts
|
|
257
|
+
- https://www.unpkg.com/@e-mc/types@0.13.7/lib/settings.d.ts
|
|
258
258
|
|
|
259
259
|
* https://www.npmjs.com/package/@types/node
|
|
260
260
|
|
package/http/adapter/index.js
CHANGED
|
@@ -355,7 +355,12 @@ class HttpAdapter {
|
|
|
355
355
|
result = new (require(packageName = 'fast-xml-parser').XMLParser)(parser).parse(buffer);
|
|
356
356
|
break;
|
|
357
357
|
case 'toml':
|
|
358
|
-
|
|
358
|
+
try {
|
|
359
|
+
result = require('smol-toml').parse(buffer);
|
|
360
|
+
}
|
|
361
|
+
catch {
|
|
362
|
+
result = require(packageName = 'toml').parse(buffer);
|
|
363
|
+
}
|
|
359
364
|
break;
|
|
360
365
|
default:
|
|
361
366
|
result = JSON.parse(buffer);
|
|
@@ -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/http/host/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const tls = require("node:tls");
|
|
3
3
|
const types_1 = require("@e-mc/types");
|
|
4
|
+
const altsvc_1 = require("@e-mc/request/http/host/altsvc");
|
|
4
5
|
const HOST_LOCAL = new Set(['localhost']);
|
|
5
6
|
const HOST_STREAM = new Map();
|
|
6
7
|
const HOST_HTTP_1_1 = [];
|
|
@@ -11,6 +12,7 @@ for (const network of Object.entries(require('node:os').networkInterfaces())) {
|
|
|
11
12
|
HOST_LOCAL.add(address);
|
|
12
13
|
}
|
|
13
14
|
}
|
|
15
|
+
const createData = () => ({ success: 0, failed: 0, errors: 0, alpn: 1, status: -1 });
|
|
14
16
|
class HttpHost {
|
|
15
17
|
static normalizeOrigin(value) {
|
|
16
18
|
return (value = value.trim()).replace(/\/+$/, '') + (!/:\d+$/.test(value) ? ':' + (value.startsWith('https') ? '443' : '80') : '');
|
|
@@ -61,19 +63,14 @@ class HttpHost {
|
|
|
61
63
|
localhost;
|
|
62
64
|
_tlsConnect = null;
|
|
63
65
|
#version;
|
|
64
|
-
#altSvc = [];
|
|
65
|
-
#altSvcQueue = [];
|
|
66
|
-
#altSvcError = [];
|
|
67
66
|
#protocol;
|
|
68
67
|
#secure;
|
|
69
68
|
#hostname;
|
|
70
69
|
#port;
|
|
71
70
|
#origin;
|
|
72
71
|
#streamSize;
|
|
73
|
-
#versionData = [
|
|
74
|
-
|
|
75
|
-
[0, 0, 0, -1, -1]
|
|
76
|
-
];
|
|
72
|
+
#versionData = [createData(), createData()];
|
|
73
|
+
#altSvc;
|
|
77
74
|
constructor(url, httpVersion = 1) {
|
|
78
75
|
const { protocol, hostname } = url;
|
|
79
76
|
const secure = protocol === 'https:';
|
|
@@ -86,6 +83,7 @@ class HttpHost {
|
|
|
86
83
|
this.#origin = url.origin;
|
|
87
84
|
this.localhost = HOST_LOCAL.has(hostname);
|
|
88
85
|
this.#streamSize = HOST_STREAM.get(address) || (this.localhost ? 65536 : 4096);
|
|
86
|
+
this.#altSvc = new altsvc_1(this, this.#versionData);
|
|
89
87
|
if (protocol !== 'file:' && !HOST_HTTP_1_1.includes(address = protocol + '//' + address)) {
|
|
90
88
|
if (secure) {
|
|
91
89
|
this.#version = HOST_ALPN_H2.includes(address) ? 2 : httpVersion;
|
|
@@ -98,7 +96,7 @@ class HttpHost {
|
|
|
98
96
|
}
|
|
99
97
|
this.#version = 1;
|
|
100
98
|
for (const version of this.#versionData) {
|
|
101
|
-
version
|
|
99
|
+
version.status = 0;
|
|
102
100
|
}
|
|
103
101
|
}
|
|
104
102
|
async hasProtocol(version) {
|
|
@@ -107,17 +105,17 @@ class HttpHost {
|
|
|
107
105
|
if (!data || !this.secure) {
|
|
108
106
|
return 0;
|
|
109
107
|
}
|
|
110
|
-
|
|
111
|
-
switch (status) {
|
|
108
|
+
switch (data.alpn) {
|
|
112
109
|
case 0:
|
|
113
110
|
case 1:
|
|
114
|
-
return
|
|
111
|
+
return data.alpn;
|
|
115
112
|
default:
|
|
116
113
|
return this._tlsConnect ||= new Promise(resolve => {
|
|
117
114
|
const alpn = 'h' + version;
|
|
118
115
|
const socket = tls.connect(+this.port, this.hostname, { ALPNProtocols: [alpn], requestCert: true, rejectUnauthorized: false }, () => {
|
|
119
116
|
this._tlsConnect = null;
|
|
120
|
-
|
|
117
|
+
data.alpn = alpn === socket.alpnProtocol ? 1 : 0;
|
|
118
|
+
resolve(data.alpn);
|
|
121
119
|
});
|
|
122
120
|
socket
|
|
123
121
|
.setNoDelay(false)
|
|
@@ -127,7 +125,8 @@ class HttpHost {
|
|
|
127
125
|
if (this._tlsConnect) {
|
|
128
126
|
this._tlsConnect = null;
|
|
129
127
|
if (this.error(version) >= 10) {
|
|
130
|
-
|
|
128
|
+
data.alpn = 0;
|
|
129
|
+
resolve(0);
|
|
131
130
|
}
|
|
132
131
|
else {
|
|
133
132
|
resolve(2);
|
|
@@ -137,7 +136,8 @@ class HttpHost {
|
|
|
137
136
|
.on('error', () => {
|
|
138
137
|
this.failed(version);
|
|
139
138
|
this._tlsConnect = null;
|
|
140
|
-
|
|
139
|
+
data.alpn = 0;
|
|
140
|
+
resolve(0);
|
|
141
141
|
})
|
|
142
142
|
.end();
|
|
143
143
|
});
|
|
@@ -147,179 +147,132 @@ class HttpHost {
|
|
|
147
147
|
}
|
|
148
148
|
success(version, status) {
|
|
149
149
|
const data = this.#versionData[version - 1];
|
|
150
|
-
return status ? data
|
|
150
|
+
return status ? data.success : ++data.success;
|
|
151
151
|
}
|
|
152
152
|
failed(version, status) {
|
|
153
153
|
const data = this.#versionData[version - 1];
|
|
154
154
|
if (status) {
|
|
155
|
-
return data
|
|
155
|
+
return data.failed;
|
|
156
156
|
}
|
|
157
|
-
this.
|
|
158
|
-
return ++data
|
|
157
|
+
this.altSvc.clear(version);
|
|
158
|
+
return ++data.failed;
|
|
159
159
|
}
|
|
160
160
|
error(version, status) {
|
|
161
161
|
const data = this.#versionData[version - 1];
|
|
162
162
|
if (status) {
|
|
163
|
-
return data
|
|
163
|
+
return data.errors;
|
|
164
164
|
}
|
|
165
|
-
if (data
|
|
166
|
-
this.
|
|
165
|
+
if (data.status !== 2) {
|
|
166
|
+
this.altSvc.close(true);
|
|
167
167
|
}
|
|
168
|
-
return ++data
|
|
168
|
+
return ++data.errors;
|
|
169
169
|
}
|
|
170
170
|
upgrade(version, altSvc) {
|
|
171
171
|
if (altSvc && this.secure) {
|
|
172
172
|
if (altSvc === 'clear') {
|
|
173
|
-
this.
|
|
173
|
+
this.altSvc.clear();
|
|
174
174
|
return;
|
|
175
175
|
}
|
|
176
176
|
const data = this.#versionData;
|
|
177
177
|
for (let i = data.length - 1; i >= version; --i) {
|
|
178
178
|
const host = data[i];
|
|
179
|
-
if (host
|
|
179
|
+
if (host.status === 0) {
|
|
180
180
|
continue;
|
|
181
181
|
}
|
|
182
|
+
const h = i + 1;
|
|
182
183
|
const increment = (flag) => {
|
|
183
|
-
host
|
|
184
|
-
if (this.#version <
|
|
185
|
-
this.#version =
|
|
184
|
+
host.status = flag;
|
|
185
|
+
if (this.#version < h) {
|
|
186
|
+
this.#version = h;
|
|
186
187
|
return true;
|
|
187
188
|
}
|
|
188
189
|
return false;
|
|
189
190
|
};
|
|
190
|
-
const
|
|
191
|
-
const time = Date.now();
|
|
191
|
+
const available = [];
|
|
192
192
|
const hostname = this.#hostname;
|
|
193
|
-
const
|
|
194
|
-
for (const match of altSvc.matchAll(new RegExp(`h${i + 1}(?:-\\d+)?="([^:]*):(\\d+)"([^,]*)`, 'g'))) {
|
|
193
|
+
for (const match of altSvc.matchAll(new RegExp(`h${h}(?:-\\d+)?="([^:]*):(\\d+)"([^,]*)`, 'g'))) {
|
|
195
194
|
const port = match[2];
|
|
196
195
|
if (!match[1] && port === this.port) {
|
|
197
196
|
increment(2);
|
|
198
|
-
|
|
197
|
+
available.length = 0;
|
|
199
198
|
break;
|
|
200
199
|
}
|
|
201
200
|
const address = match[1] || hostname;
|
|
202
201
|
const ma = +(/ma=(\d+)/.exec(match[3])?.[1] || 86400);
|
|
203
|
-
if (
|
|
204
|
-
|
|
205
|
-
address,
|
|
202
|
+
if (this.altSvc.valid(address, port, h)) {
|
|
203
|
+
available.push({
|
|
204
|
+
hostname: address,
|
|
206
205
|
port,
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
match[3].includes('persist=1')
|
|
210
|
-
|
|
206
|
+
version: h,
|
|
207
|
+
expires: ma >= 2592000 ? NaN : Date.now() + Math.min(ma * 1000, 2147483647),
|
|
208
|
+
persist: match[3].includes('persist=1')
|
|
209
|
+
});
|
|
211
210
|
}
|
|
212
211
|
}
|
|
213
|
-
if (
|
|
214
|
-
this.
|
|
215
|
-
this
|
|
216
|
-
if (a
|
|
212
|
+
if (available.length > 0) {
|
|
213
|
+
this.altSvc.close();
|
|
214
|
+
this.altSvc.available = available.sort((a, b) => {
|
|
215
|
+
if (a.hostname === hostname) {
|
|
217
216
|
return -1;
|
|
218
217
|
}
|
|
219
|
-
if (b
|
|
218
|
+
if (b.hostname === hostname) {
|
|
220
219
|
return 1;
|
|
221
220
|
}
|
|
222
|
-
if (isNaN(a
|
|
221
|
+
if (isNaN(a.expires) || a.expires > b.expires) {
|
|
223
222
|
return -1;
|
|
224
223
|
}
|
|
225
|
-
if (isNaN(b
|
|
224
|
+
if (isNaN(b.expires) || a.expires < b.expires) {
|
|
226
225
|
return 1;
|
|
227
226
|
}
|
|
228
|
-
if (a[3] && !b[3]) {
|
|
229
|
-
return -1;
|
|
230
|
-
}
|
|
231
|
-
if (!a[3] && b[3]) {
|
|
232
|
-
return -1;
|
|
233
|
-
}
|
|
234
227
|
return 0;
|
|
235
228
|
});
|
|
236
229
|
if (increment(1)) {
|
|
237
|
-
this.
|
|
230
|
+
this.altSvc.next();
|
|
238
231
|
}
|
|
239
232
|
}
|
|
240
233
|
}
|
|
241
234
|
}
|
|
242
235
|
}
|
|
243
236
|
didAltSvc(version) {
|
|
244
|
-
return this.#versionData[version]
|
|
237
|
+
return this.#versionData[version].status !== -1;
|
|
245
238
|
}
|
|
246
239
|
nextAltSvc() {
|
|
247
|
-
|
|
248
|
-
if (queue) {
|
|
249
|
-
const [hostname, port, expires, version] = queue;
|
|
250
|
-
const timeout = expires - Date.now();
|
|
251
|
-
if (timeout < 0) {
|
|
252
|
-
return this.nextAltSvc();
|
|
253
|
-
}
|
|
254
|
-
let timer = null;
|
|
255
|
-
if (!isNaN(timeout)) {
|
|
256
|
-
timer = setTimeout(() => {
|
|
257
|
-
if (!this.nextAltSvc()) {
|
|
258
|
-
this.version = 1;
|
|
259
|
-
}
|
|
260
|
-
}, timeout);
|
|
261
|
-
}
|
|
262
|
-
this.#altSvc = [hostname, port, timer, version, this.protocol + '//' + hostname + ':' + port];
|
|
263
|
-
return true;
|
|
264
|
-
}
|
|
265
|
-
return false;
|
|
240
|
+
return this.altSvc.next();
|
|
266
241
|
}
|
|
267
242
|
closeAltSvc(error) {
|
|
268
|
-
|
|
269
|
-
if (hostname) {
|
|
270
|
-
this.#altSvc = [];
|
|
271
|
-
if (timeout) {
|
|
272
|
-
clearTimeout(timeout);
|
|
273
|
-
}
|
|
274
|
-
if (error) {
|
|
275
|
-
this.#altSvcError.push(`h${version}:${hostname}:${port}`);
|
|
276
|
-
return this.nextAltSvc();
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
return false;
|
|
243
|
+
return this.altSvc.close(error);
|
|
280
244
|
}
|
|
281
245
|
clearAltSvc(version) {
|
|
282
|
-
|
|
283
|
-
if (this.#altSvcQueue.length === 0) {
|
|
284
|
-
this.flagAltSvc(version, 0);
|
|
285
|
-
}
|
|
286
|
-
else if (!this.closeAltSvc(true)) {
|
|
287
|
-
this.flagAltSvc(version, -1);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
else {
|
|
291
|
-
this.closeAltSvc();
|
|
292
|
-
this.#altSvcQueue = [];
|
|
293
|
-
this.#altSvcError = [];
|
|
294
|
-
for (const item of this.#versionData) {
|
|
295
|
-
if (item[3]) {
|
|
296
|
-
item[4] = -1;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
246
|
+
this.altSvc.clear(version);
|
|
300
247
|
}
|
|
301
248
|
flagAltSvc(version, value) {
|
|
302
|
-
this
|
|
249
|
+
this.altSvc.flag(version, value);
|
|
303
250
|
}
|
|
304
251
|
reset() {
|
|
305
|
-
this.
|
|
252
|
+
this.altSvc.clear();
|
|
306
253
|
this.#versionData.forEach((item, index) => {
|
|
307
|
-
item
|
|
308
|
-
item
|
|
309
|
-
item
|
|
254
|
+
item.success = 0;
|
|
255
|
+
item.failed = 0;
|
|
256
|
+
item.errors = 0;
|
|
310
257
|
if (index > 0) {
|
|
311
|
-
item
|
|
258
|
+
item.alpn = -1;
|
|
312
259
|
}
|
|
313
260
|
});
|
|
314
261
|
}
|
|
262
|
+
v1() {
|
|
263
|
+
return this.#version === 1;
|
|
264
|
+
}
|
|
315
265
|
v2() {
|
|
316
266
|
return this.#version === 2;
|
|
317
267
|
}
|
|
268
|
+
get altSvc() {
|
|
269
|
+
return this.#altSvc;
|
|
270
|
+
}
|
|
318
271
|
set version(value) {
|
|
319
272
|
switch (value) {
|
|
320
273
|
case 1:
|
|
321
274
|
case 2:
|
|
322
|
-
this.
|
|
275
|
+
this.altSvc.flag(this.#version = value, -1);
|
|
323
276
|
break;
|
|
324
277
|
}
|
|
325
278
|
}
|
|
@@ -333,13 +286,13 @@ class HttpHost {
|
|
|
333
286
|
return this.#secure;
|
|
334
287
|
}
|
|
335
288
|
get hostname() {
|
|
336
|
-
return this
|
|
289
|
+
return this.altSvc.hostname || this.#hostname;
|
|
337
290
|
}
|
|
338
291
|
get port() {
|
|
339
|
-
return this
|
|
292
|
+
return this.altSvc.port || this.#port;
|
|
340
293
|
}
|
|
341
294
|
get origin() {
|
|
342
|
-
return this
|
|
295
|
+
return this.altSvc.origin || this.#origin;
|
|
343
296
|
}
|
|
344
297
|
get streamSize() {
|
|
345
298
|
return this.#streamSize;
|
package/index.js
CHANGED
|
@@ -28,13 +28,14 @@ const REGEXP_GLOBWITHIN = /\\\?|(?:(?<!\\)(?:\*|\[!?[^!\]]+\]|\{(?:[^,]+,)+[^}]+
|
|
|
28
28
|
const REGEXP_RCLONE = /^rclone:\?/i;
|
|
29
29
|
const HTTP = {
|
|
30
30
|
HOST: {},
|
|
31
|
-
HEADERS:
|
|
31
|
+
HEADERS: Object.create(null),
|
|
32
|
+
CACHE: new WeakMap(),
|
|
32
33
|
VERSION: 1,
|
|
33
34
|
PROXY: null
|
|
34
35
|
};
|
|
35
36
|
const TLS = {
|
|
36
|
-
TEXT:
|
|
37
|
-
FILE:
|
|
37
|
+
TEXT: Object.create(null),
|
|
38
|
+
FILE: Object.create(null)
|
|
38
39
|
};
|
|
39
40
|
const DNS = {
|
|
40
41
|
CACHE: Object.create(null),
|
|
@@ -61,7 +62,7 @@ const ARIA2 = {
|
|
|
61
62
|
LOWEST_SPEED_LIMIT: null,
|
|
62
63
|
ALWAYS_RESUME: false,
|
|
63
64
|
FILE_ALLOCATION: 'none',
|
|
64
|
-
PROXY:
|
|
65
|
+
PROXY: Object.create(null),
|
|
65
66
|
NO_PROXY: '',
|
|
66
67
|
CONF_PATH: ''
|
|
67
68
|
};
|
|
@@ -115,21 +116,6 @@ let READ_TIMEOUT = 0;
|
|
|
115
116
|
let AGENT_TIMEOUT = 0;
|
|
116
117
|
let LOG_HTTP = false;
|
|
117
118
|
let LOG_TIMEPROCESS = true;
|
|
118
|
-
function getBaseHeaders(uri, headers) {
|
|
119
|
-
let result;
|
|
120
|
-
uri = (0, util_1.trimPath)(uri);
|
|
121
|
-
for (const pathname in headers) {
|
|
122
|
-
if (pathname === uri || uri.startsWith(pathname + '/')) {
|
|
123
|
-
(result ||= []).push([pathname, headers[pathname]]);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
if (result) {
|
|
127
|
-
if (result.length > 1) {
|
|
128
|
-
result.sort((a, b) => b[0].length - a[0].length);
|
|
129
|
-
}
|
|
130
|
-
return result[0][1];
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
119
|
function setDnsCache(hostname, value, expires) {
|
|
134
120
|
expires ??= DNS.EXPIRES;
|
|
135
121
|
if (expires > 0 && !DNS.CACHE[hostname]) {
|
|
@@ -146,11 +132,6 @@ function setDnsCache(hostname, value, expires) {
|
|
|
146
132
|
}
|
|
147
133
|
}
|
|
148
134
|
}
|
|
149
|
-
function setOutgoingHeaders(output, headers) {
|
|
150
|
-
for (const href in headers) {
|
|
151
|
-
output[href] = (0, util_1.normalizeHeaders)(headers[href]);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
135
|
function getProxySettings(request, agentTimeout) {
|
|
155
136
|
const proxy = request.proxy;
|
|
156
137
|
if (proxy && (proxy.origin || proxy.address && proxy.port)) {
|
|
@@ -175,11 +156,9 @@ function getProxySettings(request, agentTimeout) {
|
|
|
175
156
|
return null;
|
|
176
157
|
}
|
|
177
158
|
function closeTorrent(pid) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
ARIA2.PID_QUEUE.splice(index, 1);
|
|
182
|
-
}
|
|
159
|
+
const index = ARIA2.PID_QUEUE.findIndex(value => value[0] === pid);
|
|
160
|
+
if (index !== -1) {
|
|
161
|
+
ARIA2.PID_QUEUE.splice(index, 1);
|
|
183
162
|
}
|
|
184
163
|
}
|
|
185
164
|
function clearDnsLookup() {
|
|
@@ -199,9 +178,9 @@ function resetHttpHost(version) {
|
|
|
199
178
|
case 2:
|
|
200
179
|
for (const origin in HTTP.HOST) {
|
|
201
180
|
const host = HTTP.HOST[origin];
|
|
202
|
-
if (host.secure && host.
|
|
181
|
+
if (host.secure && host.v1()) {
|
|
203
182
|
const failed = host.failed(2, true);
|
|
204
|
-
if (failed === 0 && host.
|
|
183
|
+
if (failed === 0 && host.error(2, true) < 10 || failed < 3 && host.success(2, true) > 0) {
|
|
205
184
|
host.version = version;
|
|
206
185
|
}
|
|
207
186
|
}
|
|
@@ -296,50 +275,16 @@ function copySearchParams(url, base) {
|
|
|
296
275
|
}
|
|
297
276
|
});
|
|
298
277
|
}
|
|
299
|
-
function checkEncoding(request,
|
|
278
|
+
function checkEncoding(request, statusCode, contentEncoding) {
|
|
300
279
|
switch (statusCode) {
|
|
301
280
|
case 206:
|
|
302
281
|
request.emit('error', (0, types_1.errorValue)("Aborted", 'Partial content'));
|
|
303
282
|
case 204:
|
|
304
283
|
case 205:
|
|
305
284
|
case 304:
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
if (!contentEncoding) {
|
|
309
|
-
return;
|
|
310
|
-
}
|
|
311
|
-
contentEncoding = contentEncoding.trim().toLowerCase();
|
|
312
|
-
const chunkSize = outStream?.writableHighWaterMark;
|
|
313
|
-
let pipeTo;
|
|
314
|
-
if (!contentEncoding.includes(',')) {
|
|
315
|
-
pipeTo = decompressEncoding(contentEncoding, chunkSize);
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
for (const value of contentEncoding.split(/\s*,\s*/).reverse()) {
|
|
319
|
-
const next = decompressEncoding(value, chunkSize);
|
|
320
|
-
if (!next) {
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
pipeTo = pipeTo ? pipeTo.pipe(next) : next;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
if (pipeTo) {
|
|
327
|
-
if (outStream) {
|
|
328
|
-
stream.pipeline(response, pipeTo, outStream, err => {
|
|
329
|
-
if (err) {
|
|
330
|
-
response.emit('error', err);
|
|
331
|
-
}
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
|
-
else {
|
|
335
|
-
stream.pipeline(response, pipeTo, err => {
|
|
336
|
-
if (err) {
|
|
337
|
-
response.emit('error', err);
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
return pipeTo;
|
|
285
|
+
return false;
|
|
342
286
|
}
|
|
287
|
+
return !!contentEncoding;
|
|
343
288
|
}
|
|
344
289
|
function sendBody(request, options) {
|
|
345
290
|
const postData = options.postData;
|
|
@@ -351,26 +296,11 @@ function sendBody(request, options) {
|
|
|
351
296
|
}
|
|
352
297
|
request.end();
|
|
353
298
|
}
|
|
354
|
-
function decompressEncoding(value, chunkSize) {
|
|
355
|
-
switch (value) {
|
|
356
|
-
case 'gzip':
|
|
357
|
-
return zlib.createGunzip({ chunkSize });
|
|
358
|
-
case 'br':
|
|
359
|
-
return zlib.createBrotliDecompress({ chunkSize });
|
|
360
|
-
case 'deflate':
|
|
361
|
-
return zlib.createInflate({ chunkSize });
|
|
362
|
-
case 'deflate-raw':
|
|
363
|
-
return zlib.createInflateRaw({ chunkSize });
|
|
364
|
-
case 'zstd':
|
|
365
|
-
if (SUPPORTED_ZSTD) {
|
|
366
|
-
return zlib.createZstdDecompress({ chunkSize });
|
|
367
|
-
}
|
|
368
|
-
break;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
299
|
function resetAria2() {
|
|
372
|
-
|
|
373
|
-
|
|
300
|
+
if (ARIA2.PID_TIMER) {
|
|
301
|
+
clearInterval(ARIA2.PID_TIMER);
|
|
302
|
+
ARIA2.PID_TIMER = null;
|
|
303
|
+
}
|
|
374
304
|
}
|
|
375
305
|
function escapeShellQuote(value) {
|
|
376
306
|
value = value.replace(/(?<!\\)"/g, '\\"');
|
|
@@ -464,32 +394,7 @@ function setBinHeaders(args, headers) {
|
|
|
464
394
|
args.push(...items.map(value => `--header="${name}: ${escapeShellQuote(value)}"`));
|
|
465
395
|
}
|
|
466
396
|
}
|
|
467
|
-
function
|
|
468
|
-
if (binOpts) {
|
|
469
|
-
for (const leading of binOpts) {
|
|
470
|
-
if (leading.startsWith('-')) {
|
|
471
|
-
const pattern = new RegExp(`^${leading}(?:=|$)`);
|
|
472
|
-
for (let i = 0; i < opts.length; ++i) {
|
|
473
|
-
if (pattern.test(opts[i])) {
|
|
474
|
-
opts.splice(i--, i);
|
|
475
|
-
break;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
args = binOpts.concat(args);
|
|
481
|
-
}
|
|
482
|
-
if (args.length > 0) {
|
|
483
|
-
if (module_1.hasLogType(32768)) {
|
|
484
|
-
instance.formatMessage(32768, name.toUpperCase(), [bin].concat(cmd).join(' '), args.join(' '), { ...module_1.LOG_STYLE_WARN });
|
|
485
|
-
}
|
|
486
|
-
else {
|
|
487
|
-
instance.addLog(4, path.basename(bin) + ' ' + args.join(' '), name);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
return args;
|
|
491
|
-
}
|
|
492
|
-
function addAria2Proxy(args, protocol, host) {
|
|
397
|
+
function appendAria2Proxy(args, protocol, host) {
|
|
493
398
|
const { origin, username, password } = host;
|
|
494
399
|
args.push(`--${protocol}-proxy="${origin}"`);
|
|
495
400
|
if (username) {
|
|
@@ -716,7 +621,9 @@ class Request extends module_1 {
|
|
|
716
621
|
}
|
|
717
622
|
}
|
|
718
623
|
if ((0, types_1.isPlainObject)(headers)) {
|
|
719
|
-
|
|
624
|
+
for (const href in headers) {
|
|
625
|
+
HTTP.HEADERS[href] = (0, util_1.normalizeHeaders)(headers[href]);
|
|
626
|
+
}
|
|
720
627
|
}
|
|
721
628
|
if ((0, types_1.isPlainObject)(certs)) {
|
|
722
629
|
[TLS.TEXT, TLS.FILE] = validateCerts(certs);
|
|
@@ -827,9 +734,9 @@ class Request extends module_1 {
|
|
|
827
734
|
};
|
|
828
735
|
#singleton = false;
|
|
829
736
|
#httpVersion = null;
|
|
737
|
+
#headers = null;
|
|
830
738
|
#ipVersion;
|
|
831
739
|
#agentTimeout;
|
|
832
|
-
#headers = null;
|
|
833
740
|
#baseUrl = null;
|
|
834
741
|
#connectDns = Object.create(null);
|
|
835
742
|
#pendingDns = Object.create(null);
|
|
@@ -839,7 +746,7 @@ class Request extends module_1 {
|
|
|
839
746
|
#adapter = HTTP_ADAPTER;
|
|
840
747
|
#certs = null;
|
|
841
748
|
#downloading = new Set();
|
|
842
|
-
#hostInfo =
|
|
749
|
+
#hostInfo = Object.create(null);
|
|
843
750
|
#session = [Object.create(null)];
|
|
844
751
|
constructor(data) {
|
|
845
752
|
super();
|
|
@@ -865,9 +772,7 @@ class Request extends module_1 {
|
|
|
865
772
|
if (proxy) {
|
|
866
773
|
this.proxy = proxy;
|
|
867
774
|
}
|
|
868
|
-
|
|
869
|
-
setOutgoingHeaders(this.#headers = {}, headers);
|
|
870
|
-
}
|
|
775
|
+
this.parseHeaders(headers);
|
|
871
776
|
if ((0, types_1.isObject)(certs)) {
|
|
872
777
|
this.#certs = validateCerts(certs);
|
|
873
778
|
}
|
|
@@ -975,9 +880,7 @@ class Request extends module_1 {
|
|
|
975
880
|
init(config) {
|
|
976
881
|
if (config) {
|
|
977
882
|
const { headers, httpVersion, ipVersion, readTimeout } = config;
|
|
978
|
-
|
|
979
|
-
setOutgoingHeaders(this.#headers ||= {}, headers);
|
|
980
|
-
}
|
|
883
|
+
this.parseHeaders(headers);
|
|
981
884
|
if (httpVersion !== undefined) {
|
|
982
885
|
this.httpVersion = httpVersion;
|
|
983
886
|
}
|
|
@@ -1201,8 +1104,7 @@ class Request extends module_1 {
|
|
|
1201
1104
|
}
|
|
1202
1105
|
}
|
|
1203
1106
|
headersOf(uri) {
|
|
1204
|
-
|
|
1205
|
-
return headers && getBaseHeaders(uri, headers) || (this.host ? getBaseHeaders(uri, HTTP.HEADERS) : undefined);
|
|
1107
|
+
return this.findHeadersByUri(uri) || (this.host ? this.findHeadersByUri(uri, HTTP.HEADERS) : undefined);
|
|
1206
1108
|
}
|
|
1207
1109
|
async aria2c(uri, options = {}) {
|
|
1208
1110
|
if (!ARIA2.BIN) {
|
|
@@ -1220,7 +1122,7 @@ class Request extends module_1 {
|
|
|
1220
1122
|
({ pathname, headers, binOpts } = this.parseBinOpts(options, ['--daemon'], ['--input-file']));
|
|
1221
1123
|
}
|
|
1222
1124
|
try {
|
|
1223
|
-
if (
|
|
1125
|
+
if ((0, types_1.isString)(uri) && module_1.isURL(uri)) {
|
|
1224
1126
|
uri = new URL(uri);
|
|
1225
1127
|
}
|
|
1226
1128
|
pathname = checkBinTarget(this, "aria2", uri, pathname, 'aria2', binOpts);
|
|
@@ -1346,12 +1248,12 @@ class Request extends module_1 {
|
|
|
1346
1248
|
}
|
|
1347
1249
|
}
|
|
1348
1250
|
if (proxy) {
|
|
1349
|
-
|
|
1251
|
+
appendAria2Proxy(args, protocol, proxy.host);
|
|
1350
1252
|
}
|
|
1351
1253
|
else if (ARIA2.PROXY.all) {
|
|
1352
|
-
|
|
1254
|
+
appendAria2Proxy(opts, 'all', ARIA2.PROXY.all.host);
|
|
1353
1255
|
}
|
|
1354
|
-
args =
|
|
1256
|
+
args = this.mergeBinOpts(args, opts, binOpts, { name: "aria2", bin: ARIA2.BIN });
|
|
1355
1257
|
opts.push(`"${escapeShellQuote(uri)}"`);
|
|
1356
1258
|
args = args.concat(init, opts);
|
|
1357
1259
|
const startTime = Date.now();
|
|
@@ -1640,7 +1542,7 @@ class Request extends module_1 {
|
|
|
1640
1542
|
setBinHeaders(args, headers);
|
|
1641
1543
|
const cwd = module_1.isDir(pathname) ? pathname : path.dirname(pathname);
|
|
1642
1544
|
const cmd = [source, pathname];
|
|
1643
|
-
args =
|
|
1545
|
+
args = this.mergeBinOpts(args, opts, binOpts, { name: "rclone", bin: RCLONE.BIN, cmd }).concat(init, opts);
|
|
1644
1546
|
args.push(...cmd.map(value => (0, types_1.sanitizeCmd)(value)));
|
|
1645
1547
|
args.unshift(command);
|
|
1646
1548
|
const startTime = Date.now();
|
|
@@ -1866,7 +1768,8 @@ class Request extends module_1 {
|
|
|
1866
1768
|
}
|
|
1867
1769
|
connected = true;
|
|
1868
1770
|
if (this.matchStatus(statusCode, url, response, request, options) && hasResponse(statusCode)) {
|
|
1869
|
-
|
|
1771
|
+
const contentEncoding = response['content-encoding'];
|
|
1772
|
+
if (checkEncoding(request, statusCode, contentEncoding) && (emitter = this.pipeline(request, contentEncoding, outStream))) {
|
|
1870
1773
|
for (const event in listenerMap) {
|
|
1871
1774
|
const [name, type] = event.split('-');
|
|
1872
1775
|
for (const listener of listenerMap[event]) {
|
|
@@ -1942,7 +1845,7 @@ class Request extends module_1 {
|
|
|
1942
1845
|
if (proxy) {
|
|
1943
1846
|
keepAlive ??= proxy.keepAlive;
|
|
1944
1847
|
agentTimeout ??= proxy.agentTimeout;
|
|
1945
|
-
const proxyHeaders = this
|
|
1848
|
+
const proxyHeaders = this.findHeadersByUri(proxy.host.href) || this.findHeadersByUri(proxy.host.href, HTTP.HEADERS);
|
|
1946
1849
|
const pkg = secure ? 'https-proxy-agent' : 'http-proxy-agent';
|
|
1947
1850
|
try {
|
|
1948
1851
|
agent = require(pkg)(proxy.host, keepAlive === true || keepAlive === false && agentTimeout !== 0 || agentTimeout > 0 ? { ...agentOptions, keepAlive: keepAlive ?? true, timeout: agentTimeout, headers: proxyHeaders } : { ...agentOptions, headers: proxyHeaders });
|
|
@@ -1993,8 +1896,9 @@ class Request extends module_1 {
|
|
|
1993
1896
|
const statusCode = response.statusCode;
|
|
1994
1897
|
const incoming = response.headers;
|
|
1995
1898
|
if (!expectContinue && this.matchStatus(statusCode, url, incoming, request, options) && (getting || posting) && hasResponse(statusCode)) {
|
|
1996
|
-
|
|
1997
|
-
|
|
1899
|
+
const contentEncoding = incoming['content-encoding'];
|
|
1900
|
+
let source;
|
|
1901
|
+
if (checkEncoding(request, statusCode, contentEncoding) && (source = this.pipeline(response, contentEncoding, outStream))) {
|
|
1998
1902
|
source.once('finish', () => {
|
|
1999
1903
|
request.emit('end');
|
|
2000
1904
|
});
|
|
@@ -2042,7 +1946,7 @@ class Request extends module_1 {
|
|
|
2042
1946
|
if (version === 2 && incoming.upgrade?.includes('h2')) {
|
|
2043
1947
|
host.version = 2;
|
|
2044
1948
|
}
|
|
2045
|
-
else if (!host.
|
|
1949
|
+
else if (!host.altSvc.did(1)) {
|
|
2046
1950
|
host.upgrade(1, incoming['alt-svc']);
|
|
2047
1951
|
}
|
|
2048
1952
|
}
|
|
@@ -2162,13 +2066,7 @@ class Request extends module_1 {
|
|
|
2162
2066
|
else {
|
|
2163
2067
|
options = {};
|
|
2164
2068
|
}
|
|
2165
|
-
const headers = (0, util_1.parseOutgoingHeaders)(options.headers) || {};
|
|
2166
|
-
for (const attr in headers) {
|
|
2167
|
-
const name = attr.toLowerCase();
|
|
2168
|
-
if (name === 'content-type' || name === 'content-length') {
|
|
2169
|
-
delete headers[attr];
|
|
2170
|
-
}
|
|
2171
|
-
}
|
|
2069
|
+
const headers = (0, util_1.parseOutgoingHeaders)(options.headers, 'content-type', 'content-length') || {};
|
|
2172
2070
|
if (!putting && (parts || contentType === "multipart/form-data" || contentType === 'form-data')) {
|
|
2173
2071
|
let valid = false;
|
|
2174
2072
|
if ((0, types_1.isArray)(parts)) {
|
|
@@ -2317,6 +2215,57 @@ class Request extends module_1 {
|
|
|
2317
2215
|
});
|
|
2318
2216
|
this.#downloading.clear();
|
|
2319
2217
|
}
|
|
2218
|
+
pipeline(response, encoding, outStream) {
|
|
2219
|
+
const chunkSize = outStream?.writableHighWaterMark;
|
|
2220
|
+
let pipeTo;
|
|
2221
|
+
encoding = encoding.trim().toLowerCase();
|
|
2222
|
+
if (!encoding.includes(',')) {
|
|
2223
|
+
pipeTo = this.fromEncoding(encoding, { chunkSize });
|
|
2224
|
+
}
|
|
2225
|
+
else {
|
|
2226
|
+
for (const value of encoding.split(/\s*,\s*/).reverse()) {
|
|
2227
|
+
const next = this.fromEncoding(value, { chunkSize });
|
|
2228
|
+
if (!next) {
|
|
2229
|
+
return;
|
|
2230
|
+
}
|
|
2231
|
+
pipeTo = pipeTo ? pipeTo.pipe(next) : next;
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
if (pipeTo) {
|
|
2235
|
+
if (outStream) {
|
|
2236
|
+
stream.pipeline(response, pipeTo, outStream, err => {
|
|
2237
|
+
if (err) {
|
|
2238
|
+
response.emit('error', err);
|
|
2239
|
+
}
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
else {
|
|
2243
|
+
stream.pipeline(response, pipeTo, err => {
|
|
2244
|
+
if (err) {
|
|
2245
|
+
response.emit('error', err);
|
|
2246
|
+
}
|
|
2247
|
+
});
|
|
2248
|
+
}
|
|
2249
|
+
return pipeTo;
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
fromEncoding(value, options) {
|
|
2253
|
+
switch (value) {
|
|
2254
|
+
case 'gzip':
|
|
2255
|
+
return zlib.createGunzip(options);
|
|
2256
|
+
case 'br':
|
|
2257
|
+
return zlib.createBrotliDecompress(options);
|
|
2258
|
+
case 'deflate':
|
|
2259
|
+
return zlib.createInflate(options);
|
|
2260
|
+
case 'deflate-raw':
|
|
2261
|
+
return zlib.createInflateRaw(options);
|
|
2262
|
+
case 'zstd':
|
|
2263
|
+
if (SUPPORTED_ZSTD) {
|
|
2264
|
+
return zlib.createZstdDecompress(options);
|
|
2265
|
+
}
|
|
2266
|
+
break;
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2320
2269
|
matchStatus(code, url, headers, request, options) {
|
|
2321
2270
|
const status = this.#statusOn?.get(code);
|
|
2322
2271
|
if (status) {
|
|
@@ -2395,7 +2344,7 @@ class Request extends module_1 {
|
|
|
2395
2344
|
}
|
|
2396
2345
|
if ((0, types_1.isArray)(options.binOpts)) {
|
|
2397
2346
|
let next = false;
|
|
2398
|
-
binOpts = options.binOpts.filter((opt) => !((0, types_1.isString)(opt) && /^-[a-z].*$/i.test(opt
|
|
2347
|
+
binOpts = options.binOpts.filter((opt) => !((0, types_1.isString)(opt) && /^-[a-z].*$/i.test(opt))).map((opt) => {
|
|
2399
2348
|
if (next) {
|
|
2400
2349
|
if (!module_1.asString(opt).startsWith('--')) {
|
|
2401
2350
|
return [];
|
|
@@ -2445,6 +2394,58 @@ class Request extends module_1 {
|
|
|
2445
2394
|
}
|
|
2446
2395
|
return { pathname, headers: (0, util_1.parseOutgoingHeaders)(options.headers), binOpts };
|
|
2447
2396
|
}
|
|
2397
|
+
mergeBinOpts(args, opts, binOpts, options) {
|
|
2398
|
+
if (binOpts) {
|
|
2399
|
+
for (const leading of binOpts) {
|
|
2400
|
+
if (leading.charAt(0) === '-') {
|
|
2401
|
+
const pattern = new RegExp(`^${leading}(?:=|$)`);
|
|
2402
|
+
for (let i = 0; i < opts.length; ++i) {
|
|
2403
|
+
if (pattern.test(opts[i])) {
|
|
2404
|
+
opts.splice(i--, i);
|
|
2405
|
+
break;
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
args = binOpts.concat(args);
|
|
2411
|
+
}
|
|
2412
|
+
if (options && args.length > 0) {
|
|
2413
|
+
const { name, bin, cmd = [] } = options;
|
|
2414
|
+
if (module_1.hasLogType(32768)) {
|
|
2415
|
+
this.formatMessage(32768, name.toUpperCase(), [bin].concat(cmd).join(' '), args.join(' '), { ...module_1.LOG_STYLE_WARN });
|
|
2416
|
+
}
|
|
2417
|
+
else {
|
|
2418
|
+
this.addLog(4, path.basename(bin) + ' ' + args.join(' '), name);
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
return args;
|
|
2422
|
+
}
|
|
2423
|
+
parseHeaders(outgoing) {
|
|
2424
|
+
if ((0, types_1.isPlainObject)(outgoing)) {
|
|
2425
|
+
Object.assign(this.#headers ||= {}, outgoing);
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
findHeadersByUri(uri, outgoing = this.#headers) {
|
|
2429
|
+
if (outgoing) {
|
|
2430
|
+
const data = [];
|
|
2431
|
+
uri = (0, util_1.trimPath)(uri);
|
|
2432
|
+
for (const pathname in outgoing) {
|
|
2433
|
+
if (pathname === uri || uri.startsWith(pathname + '/')) {
|
|
2434
|
+
data.push([pathname, outgoing[pathname]]);
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
if (data.length > 0) {
|
|
2438
|
+
data.sort((a, b) => b[0].length - a[0].length);
|
|
2439
|
+
const headers = data[0][1];
|
|
2440
|
+
let result = HTTP.CACHE.get(headers);
|
|
2441
|
+
if (!result) {
|
|
2442
|
+
result = (0, util_1.normalizeHeaders)(headers);
|
|
2443
|
+
HTTP.CACHE.set(headers, result);
|
|
2444
|
+
}
|
|
2445
|
+
return result;
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2448
2449
|
set adapter(value) {
|
|
2449
2450
|
if (adapter_1.constructorOf(value)) {
|
|
2450
2451
|
this.#adapter = value;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e-mc/request",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.7",
|
|
4
4
|
"description": "Request constructor for E-mc.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"license": "BSD-3-Clause",
|
|
20
20
|
"homepage": "https://github.com/anpham6/e-mc#readme",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@e-mc/module": "0.13.
|
|
23
|
-
"@e-mc/types": "0.13.
|
|
22
|
+
"@e-mc/module": "0.13.7",
|
|
23
|
+
"@e-mc/types": "0.13.7",
|
|
24
24
|
"combined-stream": "^1.0.8",
|
|
25
25
|
"js-yaml": "^4.1.1",
|
|
26
26
|
"picomatch": "^4.0.3",
|
package/util.d.ts
CHANGED
|
@@ -6,15 +6,15 @@ import type { Readable, Writable } from 'node:stream';
|
|
|
6
6
|
|
|
7
7
|
declare namespace util {
|
|
8
8
|
function parseHeader<T = unknown>(headers: IncomingHttpHeaders, name: string): T | undefined;
|
|
9
|
-
function parseOutgoingHeaders(headers: OutgoingHttpHeaders | Headers | undefined): OutgoingHttpHeaders | undefined;
|
|
10
|
-
function normalizeHeaders(headers: OutgoingHttpHeaders): OutgoingHttpHeaders;
|
|
9
|
+
function parseOutgoingHeaders(headers: OutgoingHttpHeaders | Headers | undefined, ...ignore: string[]): OutgoingHttpHeaders | undefined;
|
|
10
|
+
function normalizeHeaders(headers: OutgoingHttpHeaders | Headers): OutgoingHttpHeaders;
|
|
11
11
|
function getBasicAuth(auth: AuthValue): string;
|
|
12
12
|
function getBasicAuth(username: unknown, password?: unknown): string;
|
|
13
13
|
function hasBasicAuth(value: string): boolean;
|
|
14
14
|
function checkRetryable(err: unknown): boolean;
|
|
15
15
|
function isRetryable(value: number, timeout?: boolean): boolean;
|
|
16
16
|
function parseHttpProxy(value?: string): HttpProxySettings | undefined;
|
|
17
|
-
function trimPath(value: string): string;
|
|
17
|
+
function trimPath(value: string, char?: string): string;
|
|
18
18
|
function asInt(value: unknown): number;
|
|
19
19
|
function asFloat(value: unknown): number;
|
|
20
20
|
function fromSeconds(value: unknown): number;
|
package/util.js
CHANGED
|
@@ -25,45 +25,63 @@ const node_util_1 = require("node:util");
|
|
|
25
25
|
const types_1 = require("@e-mc/types");
|
|
26
26
|
const module_1 = require("@e-mc/module");
|
|
27
27
|
const host_1 = require("@e-mc/request/http/host");
|
|
28
|
+
function setHeader(result, key, value) {
|
|
29
|
+
if (key === 'set-cookie') {
|
|
30
|
+
(result[key] ||= []).push(value);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
result[key] = value;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
28
36
|
const safeInt = (value) => value >= 0 ? Math.min(value, Number.MAX_SAFE_INTEGER) : NaN;
|
|
29
37
|
function parseHeader(headers, name) {
|
|
30
38
|
const value = headers[name];
|
|
31
|
-
if (!value) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
39
|
switch (name.toLowerCase()) {
|
|
35
|
-
case 'content-disposition':
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
case 'content-disposition':
|
|
41
|
+
if ((0, types_1.isString)(value)) {
|
|
42
|
+
let result;
|
|
43
|
+
for (const match of value.matchAll(/\bfilename(?:\*\s*=\s*UTF-8''([^\s;]+)|\s*=\s*(?:"([^"]+)"|([^\s;]+)))/gi)) {
|
|
44
|
+
if (match[1]) {
|
|
45
|
+
return decodeURIComponent(match[1]).trim();
|
|
46
|
+
}
|
|
47
|
+
result = (match[2] || match[3]).trim();
|
|
40
48
|
}
|
|
41
|
-
result
|
|
49
|
+
return result;
|
|
42
50
|
}
|
|
43
|
-
|
|
44
|
-
}
|
|
51
|
+
break;
|
|
45
52
|
}
|
|
46
53
|
}
|
|
47
|
-
function parseOutgoingHeaders(headers) {
|
|
54
|
+
function parseOutgoingHeaders(headers, ...ignore) {
|
|
48
55
|
if (!headers) {
|
|
49
56
|
return;
|
|
50
57
|
}
|
|
51
58
|
if (headers instanceof Headers) {
|
|
52
|
-
const result =
|
|
59
|
+
const result = Object.create(null);
|
|
53
60
|
headers.forEach((value, key) => {
|
|
54
|
-
if (key
|
|
55
|
-
(result
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
result[key] = value;
|
|
61
|
+
if (!ignore.includes(key)) {
|
|
62
|
+
setHeader(result, key, value);
|
|
59
63
|
}
|
|
60
64
|
});
|
|
61
65
|
return result;
|
|
62
66
|
}
|
|
67
|
+
if (ignore.length > 0) {
|
|
68
|
+
const result = {};
|
|
69
|
+
for (const attr in headers) {
|
|
70
|
+
const name = attr.toLowerCase();
|
|
71
|
+
if (!ignore.includes(name)) {
|
|
72
|
+
result[name] = headers[attr];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
63
77
|
return { ...headers };
|
|
64
78
|
}
|
|
65
79
|
function normalizeHeaders(headers) {
|
|
66
80
|
const result = Object.create(null);
|
|
81
|
+
if (headers instanceof Headers) {
|
|
82
|
+
headers.forEach((value, key) => setHeader(result, key, value));
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
67
85
|
for (const name in headers) {
|
|
68
86
|
let value = headers[name];
|
|
69
87
|
switch (typeof value) {
|
|
@@ -182,9 +200,11 @@ function parseHttpProxy(value, ignoreEnv) {
|
|
|
182
200
|
}
|
|
183
201
|
}
|
|
184
202
|
}
|
|
185
|
-
function trimPath(value) {
|
|
186
|
-
|
|
187
|
-
|
|
203
|
+
function trimPath(value, char = '/') {
|
|
204
|
+
while (value.at(-1) === char) {
|
|
205
|
+
value = value.slice(0, -1);
|
|
206
|
+
}
|
|
207
|
+
return value;
|
|
188
208
|
}
|
|
189
209
|
function asInt(value) {
|
|
190
210
|
switch (typeof value) {
|