@nxtedition/lib 14.3.0 → 15.0.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/app.js +24 -23
- package/errors.js +7 -7
- package/package.json +13 -10
- package/undici/index.js +192 -0
- package/undici/interceptor/abort.js +61 -0
- package/undici/interceptor/catch.js +55 -0
- package/undici/interceptor/content.js +137 -0
- package/undici/interceptor/log.js +57 -0
- package/{proxy.js → undici/interceptor/proxy.js} +97 -23
- package/undici/interceptor/redirect.js +179 -0
- package/undici/interceptor/response-body-dump.js +46 -0
- package/undici/interceptor/response-body-retry.js +155 -0
- package/undici/interceptor/response-retry.js +84 -0
- package/undici/interceptor/response-status-retry.js +96 -0
- package/undici/interceptor/signal.js +47 -0
- package/undici/utils.js +171 -0
- package/undici.js +0 -160
package/app.js
CHANGED
|
@@ -98,13 +98,14 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
98
98
|
// process.env.name is the pm2 name of the process
|
|
99
99
|
appConfig.instanceId ?? appConfig.containerId ?? process.env.name ?? os.hostname()
|
|
100
100
|
|
|
101
|
-
const userAgent =
|
|
101
|
+
const userAgent = globalThis.userAgent = (
|
|
102
102
|
appConfig.userAgent ??
|
|
103
103
|
(serviceName &&
|
|
104
104
|
`${serviceName}/${
|
|
105
105
|
serviceVersion || '*'
|
|
106
106
|
} (module:${serviceModule}; instance:${serviceInstanceId}) Node/${process.version}`) ??
|
|
107
107
|
null
|
|
108
|
+
)
|
|
108
109
|
|
|
109
110
|
const terminate = async (finalLogger) => {
|
|
110
111
|
finalLogger ??= logger
|
|
@@ -147,7 +148,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
147
148
|
module: serviceModule,
|
|
148
149
|
base: loggerConfig?.base ? { ...loggerConfig.base } : {},
|
|
149
150
|
},
|
|
150
|
-
terminate
|
|
151
|
+
terminate,
|
|
151
152
|
)
|
|
152
153
|
}
|
|
153
154
|
|
|
@@ -228,7 +229,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
228
229
|
} else {
|
|
229
230
|
return {}
|
|
230
231
|
}
|
|
231
|
-
})
|
|
232
|
+
}),
|
|
232
233
|
)
|
|
233
234
|
|
|
234
235
|
if (couchConfig.url) {
|
|
@@ -256,7 +257,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
256
257
|
} else {
|
|
257
258
|
return {}
|
|
258
259
|
}
|
|
259
|
-
})
|
|
260
|
+
}),
|
|
260
261
|
)
|
|
261
262
|
|
|
262
263
|
if (!dsConfig.credentials || !dsConfig.url) {
|
|
@@ -310,7 +311,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
310
311
|
|
|
311
312
|
logger[level](
|
|
312
313
|
{ ds: { connectionState, username: userName, url: dsConfig.url } },
|
|
313
|
-
'Deepstream Connection State Changed.'
|
|
314
|
+
'Deepstream Connection State Changed.',
|
|
314
315
|
)
|
|
315
316
|
|
|
316
317
|
prevConnectionState = connectionState
|
|
@@ -351,7 +352,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
351
352
|
rx.exhaustMap(() => {
|
|
352
353
|
const ret = appConfig.stats({ ds, couch, logger })
|
|
353
354
|
return ret?.then || ret?.subscribe ? ret : rxjs.of(ret)
|
|
354
|
-
})
|
|
355
|
+
}),
|
|
355
356
|
)
|
|
356
357
|
} else if (typeof appConfig.stats === 'object') {
|
|
357
358
|
stats$ = rxjs.timer(0, 10e3).pipe(rx.map(() => appConfig.stats))
|
|
@@ -369,12 +370,12 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
369
370
|
rx.retryWhen((err$) =>
|
|
370
371
|
err$.pipe(
|
|
371
372
|
rx.tap((err) => logger.error({ err }, 'monitor.stats')),
|
|
372
|
-
rx.delay(10e3)
|
|
373
|
-
)
|
|
373
|
+
rx.delay(10e3),
|
|
374
|
+
),
|
|
374
375
|
),
|
|
375
376
|
rx.startWith({}),
|
|
376
377
|
rx.publishReplay(1),
|
|
377
|
-
rx.refCount()
|
|
378
|
+
rx.refCount(),
|
|
378
379
|
)
|
|
379
380
|
|
|
380
381
|
monitorProviders.stats$ = stats$
|
|
@@ -393,7 +394,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
393
394
|
heap: v8.getHeapStatistics(),
|
|
394
395
|
...stats,
|
|
395
396
|
},
|
|
396
|
-
'STATS'
|
|
397
|
+
'STATS',
|
|
397
398
|
)
|
|
398
399
|
elu1 = elu2
|
|
399
400
|
}
|
|
@@ -422,7 +423,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
422
423
|
})
|
|
423
424
|
.pipe(
|
|
424
425
|
rx.catchError((err) => rxjs.of({ warnings: [err.message] })),
|
|
425
|
-
rx.repeatWhen(() => rxjs.timer(10e3))
|
|
426
|
+
rx.repeatWhen(() => rxjs.timer(10e3)),
|
|
426
427
|
)
|
|
427
428
|
} else if (appConfig.status && typeof appConfig.status === 'object') {
|
|
428
429
|
status$ = rxjs.timer(0, 10e3).pipe(rx.exhaustMap(() => appConfig.status))
|
|
@@ -448,7 +449,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
448
449
|
}),
|
|
449
450
|
rx.startWith([]),
|
|
450
451
|
rx.distinctUntilChanged(fp.isEqual),
|
|
451
|
-
rx.repeatWhen((complete$) => complete$.pipe(rx.delay(10e3)))
|
|
452
|
+
rx.repeatWhen((complete$) => complete$.pipe(rx.delay(10e3))),
|
|
452
453
|
),
|
|
453
454
|
toobusy
|
|
454
455
|
? rxjs.timer(0, 1e3).pipe(
|
|
@@ -462,10 +463,10 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
462
463
|
msg: `lag: ${toobusy.lag()}`,
|
|
463
464
|
},
|
|
464
465
|
]
|
|
465
|
-
: []
|
|
466
|
+
: [],
|
|
466
467
|
),
|
|
467
468
|
rx.startWith([]),
|
|
468
|
-
rx.distinctUntilChanged(fp.isEqual)
|
|
469
|
+
rx.distinctUntilChanged(fp.isEqual),
|
|
469
470
|
)
|
|
470
471
|
: rxjs.of({}),
|
|
471
472
|
couch
|
|
@@ -485,7 +486,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
485
486
|
}
|
|
486
487
|
}),
|
|
487
488
|
rx.startWith([]),
|
|
488
|
-
rx.distinctUntilChanged(fp.isEqual)
|
|
489
|
+
rx.distinctUntilChanged(fp.isEqual),
|
|
489
490
|
)
|
|
490
491
|
: rxjs.of({}),
|
|
491
492
|
ds
|
|
@@ -562,7 +563,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
562
563
|
}
|
|
563
564
|
|
|
564
565
|
return messages
|
|
565
|
-
})
|
|
566
|
+
}),
|
|
566
567
|
)
|
|
567
568
|
.subscribe(o)
|
|
568
569
|
|
|
@@ -573,7 +574,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
573
574
|
}).pipe(rx.startWith([]), rx.distinctUntilChanged(fp.isEqual))
|
|
574
575
|
: rxjs.of({}),
|
|
575
576
|
rxjs.timer(0, 10e3),
|
|
576
|
-
].filter(Boolean)
|
|
577
|
+
].filter(Boolean),
|
|
577
578
|
)
|
|
578
579
|
.pipe(
|
|
579
580
|
rx.auditTime(1e3),
|
|
@@ -597,7 +598,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
597
598
|
...message,
|
|
598
599
|
message: undefined,
|
|
599
600
|
msg: message.message,
|
|
600
|
-
}
|
|
601
|
+
},
|
|
601
602
|
)
|
|
602
603
|
.map((message) =>
|
|
603
604
|
message.id
|
|
@@ -605,9 +606,9 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
605
606
|
: {
|
|
606
607
|
...message,
|
|
607
608
|
id: hashString(
|
|
608
|
-
[message.msg, message].find(fp.isString) ?? JSON.stringify(message)
|
|
609
|
+
[message.msg, message].find(fp.isString) ?? JSON.stringify(message),
|
|
609
610
|
),
|
|
610
|
-
}
|
|
611
|
+
},
|
|
611
612
|
)
|
|
612
613
|
|
|
613
614
|
return { ...status, messages, timestamp: Date.now() }
|
|
@@ -622,7 +623,7 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
622
623
|
rx.startWith({}),
|
|
623
624
|
rx.distinctUntilChanged(fp.isEqual),
|
|
624
625
|
rx.publishReplay(1),
|
|
625
|
-
rx.refCount()
|
|
626
|
+
rx.refCount(),
|
|
626
627
|
)
|
|
627
628
|
|
|
628
629
|
const loggerSubscription = status$
|
|
@@ -747,13 +748,13 @@ module.exports = function (appConfig, onTerminate) {
|
|
|
747
748
|
},
|
|
748
749
|
]
|
|
749
750
|
.flat()
|
|
750
|
-
.filter(Boolean)
|
|
751
|
+
.filter(Boolean),
|
|
751
752
|
)
|
|
752
753
|
|
|
753
754
|
server = createServer(
|
|
754
755
|
typeof appConfig.http === 'object' ? appConfig.http : {},
|
|
755
756
|
{ ds, couch, config: httpConfig, logger },
|
|
756
|
-
middleware
|
|
757
|
+
middleware,
|
|
757
758
|
)
|
|
758
759
|
|
|
759
760
|
if (httpConfig.keepAlive != null) {
|
package/errors.js
CHANGED
|
@@ -3,8 +3,8 @@ const fp = require('lodash/fp.js')
|
|
|
3
3
|
const { toString } = Object.prototype
|
|
4
4
|
|
|
5
5
|
module.exports.AbortError = class AbortError extends Error {
|
|
6
|
-
constructor() {
|
|
7
|
-
super('The operation was aborted')
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message ?? 'The operation was aborted')
|
|
8
8
|
this.code = 'ABORT_ERR'
|
|
9
9
|
this.name = 'AbortError'
|
|
10
10
|
}
|
|
@@ -34,7 +34,7 @@ module.exports.parseError = function parseError(error) {
|
|
|
34
34
|
{
|
|
35
35
|
...properties,
|
|
36
36
|
cause: cause ? parseError(error.cause) : undefined,
|
|
37
|
-
}
|
|
37
|
+
},
|
|
38
38
|
)
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -101,7 +101,7 @@ module.exports.serializeError = function serializeError(error) {
|
|
|
101
101
|
data,
|
|
102
102
|
cause,
|
|
103
103
|
errors,
|
|
104
|
-
})
|
|
104
|
+
}),
|
|
105
105
|
)
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -115,7 +115,7 @@ module.exports.makeMessages = function makeMessages(error, options) {
|
|
|
115
115
|
return fp.pipe(
|
|
116
116
|
fp.flattenDeep,
|
|
117
117
|
fp.flatMap((x) => makeMessages(x, null)),
|
|
118
|
-
fp.uniqBy('id')
|
|
118
|
+
fp.uniqBy('id'),
|
|
119
119
|
)(error)
|
|
120
120
|
} else if (Array.isArray(error.messages)) {
|
|
121
121
|
return makeMessages(error.messages, null)
|
|
@@ -127,11 +127,11 @@ module.exports.makeMessages = function makeMessages(error, options) {
|
|
|
127
127
|
const level = parseInt(error.level) || options?.level || 50
|
|
128
128
|
const code =
|
|
129
129
|
[error?.code, options?.codes?.[error?.code]].find(
|
|
130
|
-
(x) => typeof x === 'string' && x.length > 0
|
|
130
|
+
(x) => typeof x === 'string' && x.length > 0,
|
|
131
131
|
) ?? undefined
|
|
132
132
|
const msg =
|
|
133
133
|
[error.msg, error.message, code?.toLowerCase().replace('_', ' ')].find(
|
|
134
|
-
(x) => typeof x === 'string' && x.length > 0
|
|
134
|
+
(x) => typeof x === 'string' && x.length > 0,
|
|
135
135
|
) || 'unknown error'
|
|
136
136
|
|
|
137
137
|
let data = error.data
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/lib",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "15.0.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Robert Nagy <robert.nagy@boffins.se>",
|
|
6
6
|
"files": [
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"ass.js",
|
|
9
9
|
"rxjs/*",
|
|
10
10
|
"util/*",
|
|
11
|
+
"undici/*",
|
|
11
12
|
"subtract-ranges.js",
|
|
12
13
|
"serializers.js",
|
|
13
14
|
"elasticsearch.js",
|
|
@@ -22,9 +23,7 @@
|
|
|
22
23
|
"app.js",
|
|
23
24
|
"errors.js",
|
|
24
25
|
"worker.js",
|
|
25
|
-
"proxy.js",
|
|
26
26
|
"stream.js",
|
|
27
|
-
"undici.js",
|
|
28
27
|
"timeline.js",
|
|
29
28
|
"docker-secrets.js"
|
|
30
29
|
],
|
|
@@ -71,6 +70,7 @@
|
|
|
71
70
|
"/__tests__"
|
|
72
71
|
],
|
|
73
72
|
"dependencies": {
|
|
73
|
+
"cache-control-parser": "^2.0.4",
|
|
74
74
|
"date-fns": "^2.29.3",
|
|
75
75
|
"fast-querystring": "^1.1.1",
|
|
76
76
|
"hasha": "^5.2.2",
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"json5": "^2.2.3",
|
|
79
79
|
"koa-compose": "^4.1.0",
|
|
80
80
|
"lodash": "^4.17.21",
|
|
81
|
+
"lru-cache": "^10.0.1",
|
|
81
82
|
"mime": "^3.0.0",
|
|
82
83
|
"moment-timezone": "^0.5.43",
|
|
83
84
|
"nconf": "^0.12.0",
|
|
@@ -90,23 +91,25 @@
|
|
|
90
91
|
"smpte-timecode": "^1.3.3",
|
|
91
92
|
"split-string": "^6.0.0",
|
|
92
93
|
"toobusy-js": "^0.5.1",
|
|
93
|
-
"undici": "^5.
|
|
94
|
+
"undici": "^5.25.2",
|
|
94
95
|
"url-join": "^4.0.0",
|
|
95
96
|
"xuid": "^4.1.2"
|
|
96
97
|
},
|
|
97
98
|
"devDependencies": {
|
|
98
|
-
"
|
|
99
|
-
"eslint
|
|
99
|
+
"@types/node": "^20.6.3",
|
|
100
|
+
"eslint": "^8.50.0",
|
|
101
|
+
"eslint-config-prettier": "^9.0.0",
|
|
100
102
|
"eslint-config-standard": "^17.0.0",
|
|
101
|
-
"eslint-plugin-import": "^2.
|
|
102
|
-
"eslint-plugin-n": "^
|
|
103
|
+
"eslint-plugin-import": "^2.28.1",
|
|
104
|
+
"eslint-plugin-n": "^16.1.0",
|
|
103
105
|
"eslint-plugin-node": "^11.1.0",
|
|
104
106
|
"eslint-plugin-promise": "^6.0.0",
|
|
105
107
|
"husky": "^8.0.3",
|
|
106
|
-
"lint-staged": "^
|
|
108
|
+
"lint-staged": "^14.0.1",
|
|
107
109
|
"pinst": "^3.0.0",
|
|
108
|
-
"prettier": "^
|
|
110
|
+
"prettier": "^3.0.3",
|
|
109
111
|
"rxjs": "^7.5.6",
|
|
112
|
+
"send": "^0.18.0",
|
|
110
113
|
"tap": "^16.3.4"
|
|
111
114
|
},
|
|
112
115
|
"peerDependencies": {
|
package/undici/index.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
const assert = require('assert')
|
|
2
|
+
const createError = require('http-errors')
|
|
3
|
+
const xuid = require('xuid')
|
|
4
|
+
const undici = require('undici')
|
|
5
|
+
const stream = require('stream')
|
|
6
|
+
const { parseHeaders } = require('../http')
|
|
7
|
+
|
|
8
|
+
class Readable extends stream.Readable {
|
|
9
|
+
constructor({ statusCode, statusMessage, headers, ...opts }) {
|
|
10
|
+
super(opts)
|
|
11
|
+
this.statusCode = statusCode
|
|
12
|
+
this.statusMessage = statusMessage
|
|
13
|
+
this.headers = headers
|
|
14
|
+
this.body = this
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async text() {
|
|
18
|
+
const dec = new TextDecoder()
|
|
19
|
+
let str = ''
|
|
20
|
+
for await (const chunk of this) {
|
|
21
|
+
if (typeof chunk === 'string') {
|
|
22
|
+
str += chunk
|
|
23
|
+
} else {
|
|
24
|
+
str += dec.decode(chunk, { stream: true })
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Flush the streaming TextDecoder so that any pending
|
|
28
|
+
// incomplete multibyte characters are handled.
|
|
29
|
+
str += dec.decode(undefined, { stream: false })
|
|
30
|
+
return str
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async json() {
|
|
34
|
+
return JSON.parse(await this.text())
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async arrayBuffer() {
|
|
38
|
+
const buffers = []
|
|
39
|
+
for await (const chunk of this) {
|
|
40
|
+
buffers.push(chunk)
|
|
41
|
+
}
|
|
42
|
+
return Buffer.concat(buffers)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async buffer() {
|
|
46
|
+
return Buffer.from(await this.arrayBuffer())
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async dump() {
|
|
50
|
+
let n = 0
|
|
51
|
+
try {
|
|
52
|
+
for await (const chunk of this) {
|
|
53
|
+
// do nothing
|
|
54
|
+
n += chunk.length
|
|
55
|
+
if (n > 128 * 1024) {
|
|
56
|
+
break
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
} catch {
|
|
60
|
+
this.destroy()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const dispatchers = {
|
|
66
|
+
abort: require('./interceptor/abort.js'),
|
|
67
|
+
catch: require('./interceptor/catch.js'),
|
|
68
|
+
content: require('./interceptor/content.js'),
|
|
69
|
+
responseBodyDump: require('./interceptor/response-body-dump.js'),
|
|
70
|
+
log: require('./interceptor/log.js'),
|
|
71
|
+
redirect: require('./interceptor/redirect.js'),
|
|
72
|
+
responseBodyRetry: require('./interceptor/response-body-retry.js'),
|
|
73
|
+
responseStatusRetry: require('./interceptor/response-status-retry.js'),
|
|
74
|
+
responseRetry: require('./interceptor/response-retry.js'),
|
|
75
|
+
signal: require('./interceptor/signal.js'),
|
|
76
|
+
proxy: require('./interceptor/proxy.js'),
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function request(urlOrOpts, opts = {}) {
|
|
80
|
+
let url
|
|
81
|
+
if (typeof urlOrOpts === 'string') {
|
|
82
|
+
url = new URL(urlOrOpts)
|
|
83
|
+
} else if (urlOrOpts instanceof URL) {
|
|
84
|
+
url = urlOrOpts
|
|
85
|
+
} else if (typeof urlOrOpts?.origin === 'string' && typeof urlOrOpts?.path === 'string') {
|
|
86
|
+
url = urlOrOpts
|
|
87
|
+
} else if (typeof urlOrOpts === 'object' && urlOrOpts != null) {
|
|
88
|
+
opts = urlOrOpts
|
|
89
|
+
url = opts.url
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const method = opts.method ?? (opts.body ? 'POST' : 'GET')
|
|
93
|
+
const idempotent = opts.idempotent ?? (method === 'GET' || method === 'HEAD')
|
|
94
|
+
const dump = opts.dump ?? method === 'HEAD'
|
|
95
|
+
|
|
96
|
+
let headers
|
|
97
|
+
if (Array.isArray(opts.headers)) {
|
|
98
|
+
headers = parseHeaders(opts.headers)
|
|
99
|
+
} else {
|
|
100
|
+
headers = opts.headers
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
opts = {
|
|
104
|
+
url,
|
|
105
|
+
method,
|
|
106
|
+
body: opts.body,
|
|
107
|
+
headers: {
|
|
108
|
+
'request-id': xuid(),
|
|
109
|
+
'user-agent': opts.userAgent ?? globalThis.userAgent,
|
|
110
|
+
...headers,
|
|
111
|
+
},
|
|
112
|
+
origin: opts.origin ?? url.origin,
|
|
113
|
+
path: opts.path ?? url.search ? `${url.pathname}${url.search ?? ''}` : url.pathname,
|
|
114
|
+
reset: opts.reset ?? false,
|
|
115
|
+
headersTimeout: opts.headersTimeout,
|
|
116
|
+
bodyTimeout: opts.bodyTimeout,
|
|
117
|
+
idempotent,
|
|
118
|
+
signal: opts.signal,
|
|
119
|
+
retry: opts.retry ?? 8,
|
|
120
|
+
follow: { count: opts.maxRedirections ?? 8, ...opts.redirect, ...opts.follow },
|
|
121
|
+
dump,
|
|
122
|
+
logger: opts.logger,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const dispatcher = opts.dispatcher ?? undici.getGlobalDispatcher()
|
|
126
|
+
|
|
127
|
+
return new Promise((resolve) => {
|
|
128
|
+
let dispatch = (opts, handler) => dispatcher.dispatch(opts, handler)
|
|
129
|
+
|
|
130
|
+
dispatch = dispatchers.catch(dispatch)
|
|
131
|
+
dispatch = dispatchers.abort(dispatch)
|
|
132
|
+
dispatch = dispatchers.log(dispatch)
|
|
133
|
+
dispatch = dispatchers.responseRetry(dispatch)
|
|
134
|
+
dispatch = dispatchers.responseStatusRetry(dispatch)
|
|
135
|
+
dispatch = dispatchers.responseBodyRetry(dispatch)
|
|
136
|
+
dispatch = dispatchers.content(dispatch)
|
|
137
|
+
dispatch = dispatchers.responseBodyDump(dispatch)
|
|
138
|
+
dispatch = dispatchers.redirect(dispatch)
|
|
139
|
+
dispatch = dispatchers.signal(dispatch)
|
|
140
|
+
dispatch = dispatchers.proxy(dispatch)
|
|
141
|
+
|
|
142
|
+
dispatch(opts, {
|
|
143
|
+
resolve,
|
|
144
|
+
/** @type {Function | null} */ abort: null,
|
|
145
|
+
/** @type {stream.Readable | null} */ body: null,
|
|
146
|
+
onConnect(abort) {
|
|
147
|
+
this.abort = abort
|
|
148
|
+
},
|
|
149
|
+
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
150
|
+
assert(this.abort)
|
|
151
|
+
|
|
152
|
+
const headers = parseHeaders(rawHeaders)
|
|
153
|
+
|
|
154
|
+
if (statusCode >= 400) {
|
|
155
|
+
this.abort(createError(statusCode, { headers }))
|
|
156
|
+
} else {
|
|
157
|
+
assert(statusCode >= 200)
|
|
158
|
+
|
|
159
|
+
this.body = new Readable({
|
|
160
|
+
read: resume,
|
|
161
|
+
highWaterMark: 128 * 1024,
|
|
162
|
+
statusCode,
|
|
163
|
+
statusMessage,
|
|
164
|
+
headers,
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
this.resolve(this.body)
|
|
168
|
+
this.resolve = null
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return false
|
|
172
|
+
},
|
|
173
|
+
onData(chunk) {
|
|
174
|
+
assert(this.body)
|
|
175
|
+
return this.body.push(chunk)
|
|
176
|
+
},
|
|
177
|
+
onComplete() {
|
|
178
|
+
assert(this.body)
|
|
179
|
+
this.body.push(null)
|
|
180
|
+
},
|
|
181
|
+
onError(err) {
|
|
182
|
+
if (this.body) {
|
|
183
|
+
this.body.destroy(err)
|
|
184
|
+
} else {
|
|
185
|
+
this.resolve(Promise.reject(err))
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
})
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
module.exports = { request }
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const { AbortError } = require('../../errors')
|
|
2
|
+
|
|
3
|
+
class Handler {
|
|
4
|
+
constructor(opts, { handler }) {
|
|
5
|
+
this.handler = handler
|
|
6
|
+
this.pos = 0
|
|
7
|
+
this.reason = null
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
onConnect(abort) {
|
|
11
|
+
this.abort = abort
|
|
12
|
+
this.handler.onConnect((reason) => {
|
|
13
|
+
this.reason = reason ?? new AbortError()
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
onBodySent(chunk) {
|
|
18
|
+
return this.handler.onBodySent(chunk)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
22
|
+
if (this.reason == null) {
|
|
23
|
+
const ret = this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
24
|
+
if (this.reason == null) {
|
|
25
|
+
return ret
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return true
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
onData(chunk) {
|
|
33
|
+
if (this.reason == null) {
|
|
34
|
+
const ret = this.handler.onData(chunk)
|
|
35
|
+
if (this.reason == null) {
|
|
36
|
+
return ret
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.pos += chunk.length
|
|
41
|
+
if (this.pos < 128 * 1024) {
|
|
42
|
+
return true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.abort(this.reason)
|
|
46
|
+
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
onComplete(rawTrailers) {
|
|
51
|
+
return this.reason == null
|
|
52
|
+
? this.handler.onComplete(rawTrailers)
|
|
53
|
+
: this.handler.onError(this.reason)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
onError(err) {
|
|
57
|
+
return this.handler.onError(err)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = (dispatch) => (opts, handler) => dispatch(opts, new Handler(opts, { handler }))
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
class Handler {
|
|
2
|
+
constructor(opts, { handler }) {
|
|
3
|
+
this.handler = handler
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
onConnect(abort) {
|
|
7
|
+
this.abort = abort
|
|
8
|
+
try {
|
|
9
|
+
return this.handler.onConnect(abort)
|
|
10
|
+
} catch (err) {
|
|
11
|
+
this.abort(err)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
onBodySent(chunk) {
|
|
16
|
+
try {
|
|
17
|
+
return this.handler.onBodySent(chunk)
|
|
18
|
+
} catch (err) {
|
|
19
|
+
this.abort(err)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
24
|
+
try {
|
|
25
|
+
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
26
|
+
} catch (err) {
|
|
27
|
+
this.abort(err)
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
onData(chunk) {
|
|
33
|
+
try {
|
|
34
|
+
return this.handler.onData(chunk)
|
|
35
|
+
} catch (err) {
|
|
36
|
+
this.abort(err)
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
onComplete(rawTrailers) {
|
|
42
|
+
try {
|
|
43
|
+
return this.handler.onComplete(rawTrailers)
|
|
44
|
+
} catch (err) {
|
|
45
|
+
this.abort(err)
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
onError(err) {
|
|
51
|
+
return this.handler.onError(err)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = (dispatch) => (opts, handler) => dispatch(opts, new Handler(opts, { handler }))
|