@nxtedition/lib 14.1.0 → 14.1.2
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/package.json +1 -1
- package/undici.js +108 -17
package/package.json
CHANGED
package/undici.js
CHANGED
|
@@ -1,29 +1,120 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
const assert = require('assert')
|
|
2
|
+
const tp = require('timers/promises')
|
|
3
|
+
const xuid = require('xuid')
|
|
4
|
+
const { isReadableNodeStream } = require('./stream')
|
|
5
|
+
const undici = require('undici')
|
|
6
|
+
const stream = require('stream')
|
|
3
7
|
|
|
4
|
-
|
|
8
|
+
module.exports.request = async function request(
|
|
9
|
+
url,
|
|
10
|
+
{
|
|
11
|
+
logger,
|
|
12
|
+
id = xuid(),
|
|
13
|
+
retry: { count: maxRetries = 8 } = {},
|
|
14
|
+
redirect: { count: maxRedirections = 3 } = {},
|
|
15
|
+
dispatcher,
|
|
16
|
+
signal,
|
|
17
|
+
headersTimeout,
|
|
18
|
+
bodyTimeout,
|
|
19
|
+
reset = false,
|
|
20
|
+
method = 'GET',
|
|
21
|
+
body,
|
|
22
|
+
userAgent,
|
|
23
|
+
headers,
|
|
24
|
+
}
|
|
25
|
+
) {
|
|
5
26
|
const ureq = {
|
|
6
27
|
url,
|
|
7
|
-
|
|
28
|
+
method,
|
|
29
|
+
body,
|
|
8
30
|
headers: {
|
|
9
|
-
'req-id':
|
|
10
|
-
'user-agent':
|
|
11
|
-
...
|
|
31
|
+
'req-id': id,
|
|
32
|
+
'user-agent': userAgent,
|
|
33
|
+
...headers,
|
|
12
34
|
},
|
|
13
|
-
...options,
|
|
14
|
-
throwOnError: true,
|
|
15
35
|
}
|
|
16
36
|
|
|
17
|
-
logger?.
|
|
37
|
+
const upstreamLogger = logger?.child({ ureq })
|
|
18
38
|
|
|
19
|
-
|
|
39
|
+
upstreamLogger?.debug({ ureq }, 'upstream request started')
|
|
20
40
|
|
|
21
|
-
|
|
41
|
+
try {
|
|
42
|
+
/* eslint-disable no-unreachable-loop */
|
|
43
|
+
for (let retryCount = 0; true; retryCount++) {
|
|
44
|
+
try {
|
|
45
|
+
const ures = await undici.request(url, {
|
|
46
|
+
method,
|
|
47
|
+
reset,
|
|
48
|
+
body,
|
|
49
|
+
headers,
|
|
50
|
+
signal,
|
|
51
|
+
dispatcher,
|
|
52
|
+
maxRedirections,
|
|
53
|
+
throwOnError: true,
|
|
54
|
+
headersTimeout,
|
|
55
|
+
bodyTimeout,
|
|
56
|
+
})
|
|
22
57
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
58
|
+
upstreamLogger?.debug({ ureq, ures }, 'upstream request response')
|
|
59
|
+
|
|
60
|
+
if (ures.statusCode >= 300 && ures.statusCode < 400) {
|
|
61
|
+
await ures.body.dump()
|
|
62
|
+
throw new Error('maxRedirections exceeded')
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
assert(ures.statusCode >= 200 && ures.statusCode < 300)
|
|
66
|
+
|
|
67
|
+
// TODO (fix): Wrap response to handle error that can continue with range request...
|
|
68
|
+
|
|
69
|
+
return ures
|
|
70
|
+
} catch (err) {
|
|
71
|
+
if (retryCount >= maxRetries) {
|
|
72
|
+
throw err
|
|
73
|
+
}
|
|
27
74
|
|
|
28
|
-
|
|
75
|
+
if (
|
|
76
|
+
body != null &&
|
|
77
|
+
typeof body !== 'string' &&
|
|
78
|
+
!Buffer.isBuffer(body) &&
|
|
79
|
+
(!isReadableNodeStream(body) || stream.isDisturbed(body))
|
|
80
|
+
) {
|
|
81
|
+
throw err
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (method === 'HEAD' || method === 'GET') {
|
|
85
|
+
if (
|
|
86
|
+
err.code !== 'ECONNRESET' &&
|
|
87
|
+
err.code !== 'ECONNREFUSED' &&
|
|
88
|
+
err.code !== 'ENOTFOUND' &&
|
|
89
|
+
err.code !== 'ENETDOWN' &&
|
|
90
|
+
err.code !== 'ENETUNREACH' &&
|
|
91
|
+
err.code !== 'EHOSTDOWN' &&
|
|
92
|
+
err.code !== 'EHOSTUNREACH' &&
|
|
93
|
+
err.code !== 'EPIPE' &&
|
|
94
|
+
err.message !== 'other side closed' &&
|
|
95
|
+
err.statusCode !== 420 &&
|
|
96
|
+
err.statusCode !== 429 &&
|
|
97
|
+
err.statusCode !== 502 &&
|
|
98
|
+
err.statusCode !== 503 &&
|
|
99
|
+
err.statusCode !== 504
|
|
100
|
+
) {
|
|
101
|
+
throw err
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
// TODO (fix): What to do?
|
|
105
|
+
throw err
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const delay =
|
|
109
|
+
parseInt(err.headers?.['Retry-After']) * 1e3 || Math.min(10e3, retryCount * 1e3 + 1e3)
|
|
110
|
+
|
|
111
|
+
logger?.warn({ err, retryCount, delay }, 'upstream request retrying')
|
|
112
|
+
|
|
113
|
+
return tp.setTimeout(delay, undefined, { signal })
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
} catch (err) {
|
|
117
|
+
logger?.error({ err }, 'upstream request failed')
|
|
118
|
+
throw err
|
|
119
|
+
}
|
|
29
120
|
}
|