@nxtedition/nxt-undici 2.0.7 → 2.0.9
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 +0 -3
- package/lib/interceptor/log.js +6 -1
- package/lib/interceptor/redirect.js +31 -43
- package/lib/interceptor/request-content.js +3 -1
- package/lib/interceptor/response-content.js +2 -0
- package/lib/interceptor/signal.js +5 -4
- package/package.json +1 -1
- package/lib/interceptor/catch.js +0 -71
package/lib/index.js
CHANGED
|
@@ -129,7 +129,6 @@ class Readable extends stream.Readable {
|
|
|
129
129
|
const dispatchers = {
|
|
130
130
|
requestBody: (await import('./interceptor/request-body.js')).default,
|
|
131
131
|
requestBodyFactory: (await import('./interceptor/request-body-factory.js')).default,
|
|
132
|
-
catch: (await import('./interceptor/catch.js')).default,
|
|
133
132
|
responseContent: (await import('./interceptor/response-content.js')).default,
|
|
134
133
|
requestContent: (await import('./interceptor/request-content.js')).default,
|
|
135
134
|
log: (await import('./interceptor/log.js')).default,
|
|
@@ -223,7 +222,6 @@ export async function request(url, opts) {
|
|
|
223
222
|
let dispatch = dispatcherCache.get(dispatcher)
|
|
224
223
|
if (dispatch == null) {
|
|
225
224
|
dispatch = (opts, handler) => dispatcher.dispatch(opts, handler)
|
|
226
|
-
dispatch = dispatchers.catch(dispatch)
|
|
227
225
|
dispatch = dispatchers.requestBodyFactory(dispatch)
|
|
228
226
|
dispatch = dispatchers.log(dispatch)
|
|
229
227
|
dispatch = dispatchers.requestId(dispatch)
|
|
@@ -250,7 +248,6 @@ export async function request(url, opts) {
|
|
|
250
248
|
headers,
|
|
251
249
|
origin: url.origin,
|
|
252
250
|
path: url.path ?? (url.search ? `${url.pathname}${url.search ?? ''}` : url.pathname),
|
|
253
|
-
query: opts.query,
|
|
254
251
|
reset: opts.reset ?? false,
|
|
255
252
|
blocking: opts.blocking ?? false,
|
|
256
253
|
headersTimeout: opts.headersTimeout,
|
package/lib/interceptor/log.js
CHANGED
|
@@ -24,7 +24,8 @@ class Handler {
|
|
|
24
24
|
this.abort = abort
|
|
25
25
|
this.stats.start = performance.now()
|
|
26
26
|
this.logger.debug({ ureq: this.opts }, 'upstream request started')
|
|
27
|
-
|
|
27
|
+
|
|
28
|
+
return this.handler.onConnect((reason) => {
|
|
28
29
|
this.aborted = true
|
|
29
30
|
this.abort(reason)
|
|
30
31
|
})
|
|
@@ -35,6 +36,7 @@ class Handler {
|
|
|
35
36
|
socket.on('close', () => {
|
|
36
37
|
this.logger.debug('upstream request socket closed')
|
|
37
38
|
})
|
|
39
|
+
|
|
38
40
|
return this.handler.onUpgrade(statusCode, rawHeaders, socket)
|
|
39
41
|
}
|
|
40
42
|
|
|
@@ -62,6 +64,7 @@ class Handler {
|
|
|
62
64
|
},
|
|
63
65
|
'upstream request response',
|
|
64
66
|
)
|
|
67
|
+
|
|
65
68
|
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
66
69
|
}
|
|
67
70
|
|
|
@@ -71,6 +74,7 @@ class Handler {
|
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
this.pos += chunk.length
|
|
77
|
+
|
|
74
78
|
return this.handler.onData(chunk)
|
|
75
79
|
}
|
|
76
80
|
|
|
@@ -82,6 +86,7 @@ class Handler {
|
|
|
82
86
|
{ bytesRead: this.pos, elapsedTime: this.stats.end, stats: this.stats },
|
|
83
87
|
'upstream request completed',
|
|
84
88
|
)
|
|
89
|
+
|
|
85
90
|
return this.handler.onComplete(rawTrailers)
|
|
86
91
|
}
|
|
87
92
|
|
|
@@ -4,34 +4,16 @@ import { findHeader, isDisturbed, parseURL } from '../utils.js'
|
|
|
4
4
|
const redirectableStatusCodes = [300, 301, 302, 303, 307, 308]
|
|
5
5
|
|
|
6
6
|
class Handler {
|
|
7
|
-
constructor(opts, { dispatch, handler }) {
|
|
7
|
+
constructor(opts, { dispatch, handler, count = 0 }) {
|
|
8
8
|
this.dispatch = dispatch
|
|
9
9
|
this.handler = handler
|
|
10
10
|
this.opts = opts
|
|
11
|
-
this.
|
|
12
|
-
this.
|
|
13
|
-
this.reason = null
|
|
14
|
-
this.maxCount = Number.isFinite(opts.follow) ? opts.follow : opts.follow?.count ?? 0
|
|
15
|
-
|
|
16
|
-
this.count = 0
|
|
17
|
-
this.location = null
|
|
18
|
-
|
|
19
|
-
this.handler.onConnect((reason) => {
|
|
20
|
-
this.aborted = true
|
|
21
|
-
if (this.abort) {
|
|
22
|
-
this.abort(reason)
|
|
23
|
-
} else {
|
|
24
|
-
this.reason = reason
|
|
25
|
-
}
|
|
26
|
-
})
|
|
11
|
+
this.redirectOpts = null
|
|
12
|
+
this.count = count
|
|
27
13
|
}
|
|
28
14
|
|
|
29
15
|
onConnect(abort) {
|
|
30
|
-
|
|
31
|
-
abort(this.reason)
|
|
32
|
-
} else {
|
|
33
|
-
this.abort = abort
|
|
34
|
-
}
|
|
16
|
+
return this.handler.onConnect(abort)
|
|
35
17
|
}
|
|
36
18
|
|
|
37
19
|
onUpgrade(statusCode, headers, socket) {
|
|
@@ -46,10 +28,6 @@ class Handler {
|
|
|
46
28
|
return this.handler.onRequestSent()
|
|
47
29
|
}
|
|
48
30
|
|
|
49
|
-
onError(error) {
|
|
50
|
-
return this.handler.onError(error)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
31
|
onHeaders(statusCode, headers, resume, statusText) {
|
|
54
32
|
if (redirectableStatusCodes.indexOf(statusCode) === -1) {
|
|
55
33
|
return this.handler.onHeaders(statusCode, headers, resume, statusText)
|
|
@@ -59,33 +37,36 @@ class Handler {
|
|
|
59
37
|
throw new Error(`Disturbed request cannot be redirected.`)
|
|
60
38
|
}
|
|
61
39
|
|
|
62
|
-
|
|
40
|
+
const location = findHeader(headers, 'location')
|
|
63
41
|
|
|
64
|
-
if (!
|
|
42
|
+
if (!location) {
|
|
65
43
|
throw new Error(`Missing redirection location .`)
|
|
66
44
|
}
|
|
67
45
|
|
|
68
46
|
this.count += 1
|
|
69
47
|
|
|
70
48
|
if (typeof this.opts.follow === 'function') {
|
|
71
|
-
if (!this.opts.follow(
|
|
49
|
+
if (!this.opts.follow(location, this.count)) {
|
|
72
50
|
return this.handler.onHeaders(statusCode, headers, resume, statusText)
|
|
73
51
|
}
|
|
74
52
|
} else {
|
|
75
|
-
|
|
76
|
-
|
|
53
|
+
const maxCount = Number.isFinite(this.opts.follow)
|
|
54
|
+
? this.opts.follow
|
|
55
|
+
: this.opts.follow?.count ?? 0
|
|
56
|
+
if (this.count >= maxCount) {
|
|
57
|
+
throw new Error(`Max redirections reached: ${maxCount}.`)
|
|
77
58
|
}
|
|
78
59
|
}
|
|
79
60
|
|
|
80
61
|
const { origin, pathname, search } = parseURL(
|
|
81
|
-
new URL(
|
|
62
|
+
new URL(location, this.opts.origin && new URL(this.opts.path, this.opts.origin)),
|
|
82
63
|
)
|
|
83
64
|
const path = search ? `${pathname}${search}` : pathname
|
|
84
65
|
|
|
85
66
|
// Remove headers referring to the original URL.
|
|
86
67
|
// By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers.
|
|
87
68
|
// https://tools.ietf.org/html/rfc7231#section-6.4
|
|
88
|
-
this.
|
|
69
|
+
this.redirectOpts = {
|
|
89
70
|
...this.opts,
|
|
90
71
|
headers: cleanRequestHeaders(
|
|
91
72
|
this.opts.headers,
|
|
@@ -94,18 +75,17 @@ class Handler {
|
|
|
94
75
|
),
|
|
95
76
|
path,
|
|
96
77
|
origin,
|
|
97
|
-
query: null,
|
|
98
78
|
}
|
|
99
79
|
|
|
100
80
|
// https://tools.ietf.org/html/rfc7231#section-6.4.4
|
|
101
81
|
// In case of HTTP 303, always replace method to be either HEAD or GET
|
|
102
|
-
if (statusCode === 303 && this.
|
|
103
|
-
this.
|
|
82
|
+
if (statusCode === 303 && this.redirectOpts.method !== 'HEAD') {
|
|
83
|
+
this.redirectOpts = { ...this.redirectOpts, method: 'GET', body: null }
|
|
104
84
|
}
|
|
105
85
|
}
|
|
106
86
|
|
|
107
87
|
onData(chunk) {
|
|
108
|
-
if (this.
|
|
88
|
+
if (this.redirectOpts) {
|
|
109
89
|
/*
|
|
110
90
|
https://tools.ietf.org/html/rfc7231#section-6.4
|
|
111
91
|
|
|
@@ -129,7 +109,7 @@ class Handler {
|
|
|
129
109
|
}
|
|
130
110
|
|
|
131
111
|
onComplete(trailers) {
|
|
132
|
-
if (this.
|
|
112
|
+
if (this.redirectOpts) {
|
|
133
113
|
/*
|
|
134
114
|
https://tools.ietf.org/html/rfc7231#section-6.4
|
|
135
115
|
|
|
@@ -138,14 +118,22 @@ class Handler {
|
|
|
138
118
|
|
|
139
119
|
See comment on onData method above for more detailed informations.
|
|
140
120
|
*/
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
121
|
+
this.dispatch(
|
|
122
|
+
this.redirectOpts,
|
|
123
|
+
new Handler(this.redirectOpts, {
|
|
124
|
+
handler: this.handler,
|
|
125
|
+
dispatch: this.dispatch,
|
|
126
|
+
count: this.count,
|
|
127
|
+
}),
|
|
128
|
+
)
|
|
145
129
|
} else {
|
|
146
130
|
return this.handler.onComplete(trailers)
|
|
147
131
|
}
|
|
148
132
|
}
|
|
133
|
+
|
|
134
|
+
onError(error) {
|
|
135
|
+
return this.handler.onError(error)
|
|
136
|
+
}
|
|
149
137
|
}
|
|
150
138
|
|
|
151
139
|
// https://tools.ietf.org/html/rfc7231#section-6.4.4
|
|
@@ -178,5 +166,5 @@ function cleanRequestHeaders(headers, removeContent, unknownOrigin) {
|
|
|
178
166
|
|
|
179
167
|
export default (dispatch) => (opts, handler) =>
|
|
180
168
|
opts.follow != null
|
|
181
|
-
? dispatch(opts, new Handler(opts, { handler, dispatch }))
|
|
169
|
+
? dispatch(opts, new Handler(opts, { handler, dispatch, count: 0 }))
|
|
182
170
|
: dispatch(opts, handler)
|
|
@@ -12,6 +12,7 @@ class Handler {
|
|
|
12
12
|
|
|
13
13
|
onConnect(abort) {
|
|
14
14
|
this.abort = abort
|
|
15
|
+
|
|
15
16
|
return this.handler.onConnect(abort)
|
|
16
17
|
}
|
|
17
18
|
|
|
@@ -22,6 +23,7 @@ class Handler {
|
|
|
22
23
|
onBodySent(chunk) {
|
|
23
24
|
this.pos += chunk.length
|
|
24
25
|
this.hasher?.update(chunk)
|
|
26
|
+
|
|
25
27
|
return this.handler.onBodySent(chunk)
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -62,7 +64,7 @@ class Handler {
|
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
onError(err) {
|
|
65
|
-
this.handler.onError(err)
|
|
67
|
+
return this.handler.onError(err)
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
|
|
@@ -30,12 +30,14 @@ class Handler {
|
|
|
30
30
|
this.md5 = findHeader(rawHeaders, 'content-md5')
|
|
31
31
|
this.length = findHeader(rawHeaders, 'content-length')
|
|
32
32
|
this.hasher = this.md5 != null ? crypto.createHash('md5') : null
|
|
33
|
+
|
|
33
34
|
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
onData(chunk) {
|
|
37
38
|
this.pos += chunk.length
|
|
38
39
|
this.hasher?.update(chunk)
|
|
40
|
+
|
|
39
41
|
return this.handler.onData(chunk)
|
|
40
42
|
}
|
|
41
43
|
|
|
@@ -6,13 +6,12 @@ class Handler {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
onConnect(abort) {
|
|
9
|
-
this.abort = () => abort(this.signal.reason)
|
|
10
|
-
|
|
11
|
-
this.signal.addEventListener('abort', this.abort)
|
|
12
|
-
|
|
13
9
|
if (this.signal.aborted) {
|
|
14
10
|
abort(this.signal.reason)
|
|
15
11
|
} else {
|
|
12
|
+
this.abort = () => abort(this.signal.reason)
|
|
13
|
+
this.signal.addEventListener('abort', this.abort)
|
|
14
|
+
|
|
16
15
|
this.handler.onConnect(abort)
|
|
17
16
|
}
|
|
18
17
|
}
|
|
@@ -41,6 +40,7 @@ class Handler {
|
|
|
41
40
|
if (this.abort) {
|
|
42
41
|
this.signal.removeEventListener('abort', this.abort)
|
|
43
42
|
}
|
|
43
|
+
|
|
44
44
|
return this.handler.onComplete(rawTrailers)
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -48,6 +48,7 @@ class Handler {
|
|
|
48
48
|
if (this.abort) {
|
|
49
49
|
this.signal.removeEventListener('abort', this.abort)
|
|
50
50
|
}
|
|
51
|
+
|
|
51
52
|
return this.handler.onError(err)
|
|
52
53
|
}
|
|
53
54
|
}
|
package/package.json
CHANGED
package/lib/interceptor/catch.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
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
|
-
onUpgrade(statusCode, rawHeaders, socket) {
|
|
16
|
-
try {
|
|
17
|
-
return this.handler.onUpgrade(statusCode, rawHeaders, socket)
|
|
18
|
-
} catch (err) {
|
|
19
|
-
this.abort(err)
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
onBodySent(chunk) {
|
|
24
|
-
try {
|
|
25
|
-
return this.handler.onBodySent(chunk)
|
|
26
|
-
} catch (err) {
|
|
27
|
-
this.abort(err)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
onRequestSent() {
|
|
32
|
-
try {
|
|
33
|
-
return this.handler.onRequestSent()
|
|
34
|
-
} catch (err) {
|
|
35
|
-
this.abort(err)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
40
|
-
try {
|
|
41
|
-
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
42
|
-
} catch (err) {
|
|
43
|
-
this.abort(err)
|
|
44
|
-
return false
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
onData(chunk) {
|
|
49
|
-
try {
|
|
50
|
-
return this.handler.onData(chunk)
|
|
51
|
-
} catch (err) {
|
|
52
|
-
this.abort(err)
|
|
53
|
-
return false
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
onComplete(rawTrailers) {
|
|
58
|
-
try {
|
|
59
|
-
return this.handler.onComplete(rawTrailers)
|
|
60
|
-
} catch (err) {
|
|
61
|
-
this.abort(err)
|
|
62
|
-
return false
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
onError(err) {
|
|
67
|
-
return this.handler.onError(err)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export default (dispatch) => (opts, handler) => dispatch(opts, new Handler(opts, { handler }))
|