@nxtedition/nxt-undici 2.0.38 → 2.0.40
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/lib/index.js +1 -9
- package/lib/interceptor/redirect.js +5 -1
- package/lib/interceptor/response-retry-body.js +20 -0
- package/lib/readable.js +17 -2
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -3,7 +3,6 @@ import createError from 'http-errors'
|
|
|
3
3
|
import undici from 'undici'
|
|
4
4
|
import { findHeader, parseHeaders, AbortError, isStream } from './utils.js'
|
|
5
5
|
import { BodyReadable as Readable } from './readable.js'
|
|
6
|
-
import CacheableLookup from 'cacheable-lookup'
|
|
7
6
|
|
|
8
7
|
const dispatcherCache = new WeakMap()
|
|
9
8
|
|
|
@@ -33,13 +32,6 @@ const dispatchers = {
|
|
|
33
32
|
requestId: (await import('./interceptor/request-id.js')).default,
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
const dnsCache = new CacheableLookup({ maxTtl: 10e3 })
|
|
37
|
-
const defaultDispatcher = new undici.Agent({
|
|
38
|
-
connect: {
|
|
39
|
-
lookup: dnsCache.lookup,
|
|
40
|
-
},
|
|
41
|
-
})
|
|
42
|
-
|
|
43
35
|
export async function request(url, opts) {
|
|
44
36
|
// TODO (fix): More argument validation...
|
|
45
37
|
|
|
@@ -113,7 +105,7 @@ export async function request(url, opts) {
|
|
|
113
105
|
opts.body.on('error', () => {})
|
|
114
106
|
}
|
|
115
107
|
|
|
116
|
-
const dispatcher = opts.dispatcher ??
|
|
108
|
+
const dispatcher = opts.dispatcher ?? undici.getGlobalDispatcher()
|
|
117
109
|
|
|
118
110
|
let dispatch = dispatcherCache.get(dispatcher)
|
|
119
111
|
if (dispatch == null) {
|
|
@@ -17,6 +17,7 @@ class Handler {
|
|
|
17
17
|
|
|
18
18
|
this.count = 0
|
|
19
19
|
this.location = null
|
|
20
|
+
this.history = []
|
|
20
21
|
|
|
21
22
|
this.handler.onConnect((reason) => {
|
|
22
23
|
this.aborted = true
|
|
@@ -57,6 +58,7 @@ class Handler {
|
|
|
57
58
|
throw new Error(`Missing redirection location .`)
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
this.history.push(this.location)
|
|
60
62
|
this.count += 1
|
|
61
63
|
|
|
62
64
|
if (typeof this.opts.follow === 'function') {
|
|
@@ -67,7 +69,9 @@ class Handler {
|
|
|
67
69
|
}
|
|
68
70
|
} else {
|
|
69
71
|
if (this.count >= this.maxCount) {
|
|
70
|
-
throw new Error(`Max redirections reached: ${this.maxCount}.`)
|
|
72
|
+
throw Object.assign(new Error(`Max redirections reached: ${this.maxCount}.`), {
|
|
73
|
+
history: this.history,
|
|
74
|
+
})
|
|
71
75
|
}
|
|
72
76
|
}
|
|
73
77
|
|
|
@@ -171,3 +171,23 @@ export default (dispatch) => (opts, handler) => {
|
|
|
171
171
|
? dispatch(opts, new Handler(opts, { handler, dispatch }))
|
|
172
172
|
: dispatch(opts, handler)
|
|
173
173
|
}
|
|
174
|
+
export function isConnectionError(err) {
|
|
175
|
+
// AWS compat.
|
|
176
|
+
const statusCode = err?.statusCode ?? err?.$metadata?.httpStatusCode
|
|
177
|
+
return err
|
|
178
|
+
? err.code === 'ECONNRESET' ||
|
|
179
|
+
err.code === 'ECONNREFUSED' ||
|
|
180
|
+
err.code === 'ENOTFOUND' ||
|
|
181
|
+
err.code === 'ENETDOWN' ||
|
|
182
|
+
err.code === 'ENETUNREACH' ||
|
|
183
|
+
err.code === 'EHOSTDOWN' ||
|
|
184
|
+
err.code === 'EHOSTUNREACH' ||
|
|
185
|
+
err.code === 'EPIPE' ||
|
|
186
|
+
err.message === 'other side closed' ||
|
|
187
|
+
statusCode === 420 ||
|
|
188
|
+
statusCode === 429 ||
|
|
189
|
+
statusCode === 502 ||
|
|
190
|
+
statusCode === 503 ||
|
|
191
|
+
statusCode === 504
|
|
192
|
+
: false
|
|
193
|
+
}
|
package/lib/readable.js
CHANGED
|
@@ -12,6 +12,7 @@ const kReading = Symbol('kReading')
|
|
|
12
12
|
const kBody = Symbol('kBody')
|
|
13
13
|
const kAbort = Symbol('abort')
|
|
14
14
|
const kContentType = Symbol('kContentType')
|
|
15
|
+
const kReadLength = Symbol('kReadLength')
|
|
15
16
|
|
|
16
17
|
const kStatusCode = Symbol('kStatusCode')
|
|
17
18
|
const kStatusMessage = Symbol('kStatusMessage')
|
|
@@ -40,8 +41,9 @@ export class BodyReadable extends Readable {
|
|
|
40
41
|
this[kStatusCode] = statusCode
|
|
41
42
|
this[kStatusMessage] = statusMessage
|
|
42
43
|
this[kHeaders] = headers
|
|
43
|
-
this[kSize] = size
|
|
44
|
+
this[kSize] = Number.isFinite(size) ? size : null
|
|
44
45
|
this[kAbort] = abort
|
|
46
|
+
this[kReadLength] = 0
|
|
45
47
|
|
|
46
48
|
this[kConsume] = null
|
|
47
49
|
this[kBody] = null
|
|
@@ -124,7 +126,16 @@ export class BodyReadable extends Readable {
|
|
|
124
126
|
return this.off(ev, ...args)
|
|
125
127
|
}
|
|
126
128
|
|
|
129
|
+
setEncoding(encoding) {
|
|
130
|
+
if (encoding) {
|
|
131
|
+
throw new Error('not supported')
|
|
132
|
+
}
|
|
133
|
+
return super.setEncoding(encoding)
|
|
134
|
+
}
|
|
135
|
+
|
|
127
136
|
push(chunk) {
|
|
137
|
+
this[kReadLength] += chunk.length
|
|
138
|
+
|
|
128
139
|
if (this[kConsume] && chunk !== null) {
|
|
129
140
|
consumePush(this[kConsume], chunk)
|
|
130
141
|
return this[kReading] ? super.push(chunk) : true
|
|
@@ -164,9 +175,13 @@ export class BodyReadable extends Readable {
|
|
|
164
175
|
}
|
|
165
176
|
|
|
166
177
|
async dump(opts) {
|
|
167
|
-
let limit = Number.isFinite(opts?.limit) ? opts.limit :
|
|
178
|
+
let limit = Number.isFinite(opts?.limit) ? opts.limit : 128 * 1024
|
|
168
179
|
const signal = opts?.signal
|
|
169
180
|
|
|
181
|
+
if (this[kSize] != null && this[kSize] - this[kReadLength] > limit) {
|
|
182
|
+
this.destroy(signal.reason ?? new AbortError())
|
|
183
|
+
}
|
|
184
|
+
|
|
170
185
|
if (signal != null && (typeof signal !== 'object' || !('aborted' in signal))) {
|
|
171
186
|
throw new InvalidArgumentError('signal must be an AbortSignal')
|
|
172
187
|
}
|