@nxtedition/nxt-undici 2.0.15 → 2.0.17
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 +50 -37
- package/lib/interceptor/cache.js +7 -16
- package/lib/interceptor/log.js +5 -5
- package/lib/interceptor/redirect.js +6 -6
- package/lib/interceptor/request-body-factory.js +1 -1
- package/lib/interceptor/request-body.js +4 -4
- package/lib/interceptor/request-content.js +7 -6
- package/lib/interceptor/response-content.js +4 -4
- package/lib/interceptor/response-error.js +96 -0
- package/lib/interceptor/{response-body-retry.js → response-retry-body.js} +36 -29
- package/lib/interceptor/response-retry.js +18 -22
- package/lib/utils.js +47 -10
- package/package.json +1 -1
- package/lib/interceptor/response-status-retry.js +0 -104
- package/lib/interceptor/signal.js +0 -57
package/lib/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import assert from 'node:assert'
|
|
|
2
2
|
import stream from 'node:stream'
|
|
3
3
|
import createError from 'http-errors'
|
|
4
4
|
import undici from 'undici'
|
|
5
|
-
import { parseHeaders, AbortError } from './utils.js'
|
|
5
|
+
import { findHeader, parseHeaders, AbortError } from './utils.js'
|
|
6
6
|
import CacheableLookup from 'cacheable-lookup'
|
|
7
7
|
|
|
8
8
|
const dispatcherCache = new WeakMap()
|
|
@@ -25,13 +25,15 @@ const kStatusCode = Symbol('statusCode')
|
|
|
25
25
|
const kStatusMessage = Symbol('statusMessage')
|
|
26
26
|
const kHeaders = Symbol('headers')
|
|
27
27
|
const kSize = Symbol('size')
|
|
28
|
+
const kHandler = Symbol('handler')
|
|
28
29
|
|
|
29
30
|
let ABORT_ERROR
|
|
30
31
|
|
|
31
32
|
class Readable extends stream.Readable {
|
|
32
|
-
constructor({ statusCode, statusMessage, headers, size, abort, highWaterMark, resume }) {
|
|
33
|
-
super(
|
|
33
|
+
constructor(handler, { statusCode, statusMessage, headers, size, abort, highWaterMark, resume }) {
|
|
34
|
+
super({ highWaterMark })
|
|
34
35
|
|
|
36
|
+
this[kHandler] = handler
|
|
35
37
|
this[kStatusCode] = statusCode
|
|
36
38
|
this[kStatusMessage] = statusMessage
|
|
37
39
|
this[kHeaders] = headers
|
|
@@ -71,12 +73,18 @@ class Readable extends stream.Readable {
|
|
|
71
73
|
this[kAbort](err)
|
|
72
74
|
}
|
|
73
75
|
|
|
76
|
+
if (this[kHandler].signal) {
|
|
77
|
+
this[kHandler].signal.removeEventListener('abort', this[kHandler].onAbort)
|
|
78
|
+
this[kHandler].signal = null
|
|
79
|
+
}
|
|
80
|
+
|
|
74
81
|
callback(err)
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
async text() {
|
|
78
85
|
const dec = new TextDecoder()
|
|
79
86
|
let str = ''
|
|
87
|
+
|
|
80
88
|
for await (const chunk of this) {
|
|
81
89
|
if (typeof chunk === 'string') {
|
|
82
90
|
str += chunk
|
|
@@ -84,6 +92,7 @@ class Readable extends stream.Readable {
|
|
|
84
92
|
str += dec.decode(chunk, { stream: true })
|
|
85
93
|
}
|
|
86
94
|
}
|
|
95
|
+
|
|
87
96
|
// Flush the streaming TextDecoder so that any pending
|
|
88
97
|
// incomplete multibyte characters are handled.
|
|
89
98
|
str += dec.decode(undefined, { stream: false })
|
|
@@ -127,16 +136,15 @@ class Readable extends stream.Readable {
|
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
const dispatchers = {
|
|
139
|
+
responseError: (await import('./interceptor/response-error.js')).default,
|
|
130
140
|
requestBody: (await import('./interceptor/request-body.js')).default,
|
|
131
141
|
requestBodyFactory: (await import('./interceptor/request-body-factory.js')).default,
|
|
132
142
|
responseContent: (await import('./interceptor/response-content.js')).default,
|
|
133
143
|
requestContent: (await import('./interceptor/request-content.js')).default,
|
|
134
144
|
log: (await import('./interceptor/log.js')).default,
|
|
135
145
|
redirect: (await import('./interceptor/redirect.js')).default,
|
|
136
|
-
responseBodyRetry: (await import('./interceptor/response-body-retry.js')).default,
|
|
137
|
-
responseStatusRetry: (await import('./interceptor/response-status-retry.js')).default,
|
|
138
146
|
responseRetry: (await import('./interceptor/response-retry.js')).default,
|
|
139
|
-
|
|
147
|
+
responseRetryBody: (await import('./interceptor/response-retry-body.js')).default,
|
|
140
148
|
proxy: (await import('./interceptor/proxy.js')).default,
|
|
141
149
|
cache: (await import('./interceptor/cache.js')).default,
|
|
142
150
|
requestId: (await import('./interceptor/request-id.js')).default,
|
|
@@ -222,26 +230,25 @@ export async function request(url, opts) {
|
|
|
222
230
|
let dispatch = dispatcherCache.get(dispatcher)
|
|
223
231
|
if (dispatch == null) {
|
|
224
232
|
dispatch = (opts, handler) => dispatcher.dispatch(opts, handler)
|
|
233
|
+
dispatch = dispatchers.responseError(dispatch)
|
|
225
234
|
dispatch = dispatchers.requestBodyFactory(dispatch)
|
|
226
235
|
dispatch = dispatchers.log(dispatch)
|
|
227
236
|
dispatch = dispatchers.requestId(dispatch)
|
|
228
237
|
dispatch = dispatchers.responseRetry(dispatch)
|
|
229
|
-
dispatch = dispatchers.
|
|
230
|
-
dispatch = dispatchers.responseBodyRetry(dispatch)
|
|
238
|
+
dispatch = dispatchers.responseRetryBody(dispatch)
|
|
231
239
|
dispatch = dispatchers.responseContent(dispatch)
|
|
232
240
|
dispatch = dispatchers.requestContent(dispatch)
|
|
233
|
-
dispatch = dispatchers.redirect(dispatch)
|
|
234
|
-
dispatch = dispatchers.signal(dispatch)
|
|
235
241
|
dispatch = dispatchers.cache(dispatch)
|
|
242
|
+
dispatch = dispatchers.redirect(dispatch)
|
|
236
243
|
dispatch = dispatchers.proxy(dispatch)
|
|
237
244
|
dispatch = dispatchers.requestBody(dispatch)
|
|
238
245
|
dispatcherCache.set(dispatcher, dispatch)
|
|
239
246
|
}
|
|
240
247
|
|
|
241
|
-
|
|
248
|
+
return await new Promise((resolve, reject) =>
|
|
242
249
|
dispatch(
|
|
243
250
|
{
|
|
244
|
-
id: opts.id ?? headers
|
|
251
|
+
id: opts.id ?? findHeader(headers, 'request-id') ?? genReqId(),
|
|
245
252
|
url,
|
|
246
253
|
method,
|
|
247
254
|
body: opts.body,
|
|
@@ -253,7 +260,6 @@ export async function request(url, opts) {
|
|
|
253
260
|
headersTimeout: opts.headersTimeout,
|
|
254
261
|
bodyTimeout: opts.bodyTimeout,
|
|
255
262
|
idempotent,
|
|
256
|
-
signal: opts.signal,
|
|
257
263
|
retry: opts.retry ?? 8,
|
|
258
264
|
proxy: opts.proxy,
|
|
259
265
|
cache: opts.cache,
|
|
@@ -266,14 +272,28 @@ export async function request(url, opts) {
|
|
|
266
272
|
resolve,
|
|
267
273
|
reject,
|
|
268
274
|
logger: opts.logger,
|
|
275
|
+
signal: opts.signal,
|
|
269
276
|
/** @type {Function | null} */ abort: null,
|
|
270
277
|
/** @type {stream.Readable | null} */ body: null,
|
|
271
278
|
onConnect(abort) {
|
|
272
|
-
this.
|
|
279
|
+
if (this.signal?.aborted) {
|
|
280
|
+
abort(this.signal.reason)
|
|
281
|
+
} else {
|
|
282
|
+
this.abort = abort
|
|
283
|
+
|
|
284
|
+
if (this.signal) {
|
|
285
|
+
this.onAbort = () => {
|
|
286
|
+
if (this.body) {
|
|
287
|
+
this.body.destroy(this.signal.reason ?? new AbortError())
|
|
288
|
+
} else {
|
|
289
|
+
this.abort(this.signal.reason)
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
this.signal.addEventListener('abort', this.onAbort)
|
|
293
|
+
}
|
|
294
|
+
}
|
|
273
295
|
},
|
|
274
|
-
onUpgrade(statusCode, rawHeaders, socket) {
|
|
275
|
-
const headers = parseHeaders(rawHeaders)
|
|
276
|
-
|
|
296
|
+
onUpgrade(statusCode, rawHeaders, socket, headers = parseHeaders(rawHeaders)) {
|
|
277
297
|
if (statusCode !== 101) {
|
|
278
298
|
this.abort(createError(statusCode, { headers }))
|
|
279
299
|
} else {
|
|
@@ -283,14 +303,18 @@ export async function request(url, opts) {
|
|
|
283
303
|
},
|
|
284
304
|
onBodySent(chunk) {},
|
|
285
305
|
onRequestSent() {},
|
|
286
|
-
onHeaders(
|
|
287
|
-
|
|
288
|
-
|
|
306
|
+
onHeaders(
|
|
307
|
+
statusCode,
|
|
308
|
+
rawHeaders,
|
|
309
|
+
resume,
|
|
310
|
+
statusMessage,
|
|
311
|
+
headers = parseHeaders(rawHeaders),
|
|
312
|
+
) {
|
|
289
313
|
assert(statusCode >= 200)
|
|
290
314
|
|
|
291
|
-
const contentLength =
|
|
315
|
+
const contentLength = findHeader(rawHeaders, 'content-length')
|
|
292
316
|
|
|
293
|
-
this.body = new Readable({
|
|
317
|
+
this.body = new Readable(this, {
|
|
294
318
|
resume,
|
|
295
319
|
abort: this.abort,
|
|
296
320
|
highWaterMark: this.highWaterMark,
|
|
@@ -304,7 +328,7 @@ export async function request(url, opts) {
|
|
|
304
328
|
this.resolve = null
|
|
305
329
|
this.reject = null
|
|
306
330
|
|
|
307
|
-
return
|
|
331
|
+
return true
|
|
308
332
|
},
|
|
309
333
|
onData(chunk) {
|
|
310
334
|
return this.body.push(chunk)
|
|
@@ -313,6 +337,9 @@ export async function request(url, opts) {
|
|
|
313
337
|
this.body.push(null)
|
|
314
338
|
},
|
|
315
339
|
onError(err) {
|
|
340
|
+
this.signal?.removeEventListener('abort', this.onAbort)
|
|
341
|
+
this.signal = null
|
|
342
|
+
|
|
316
343
|
if (this.body) {
|
|
317
344
|
this.body.destroy(err)
|
|
318
345
|
} else {
|
|
@@ -324,18 +351,4 @@ export async function request(url, opts) {
|
|
|
324
351
|
},
|
|
325
352
|
),
|
|
326
353
|
)
|
|
327
|
-
|
|
328
|
-
if (method === 'HEAD') {
|
|
329
|
-
await res.dump()
|
|
330
|
-
} else if (res.statusCode >= 400) {
|
|
331
|
-
// TODO (fix): Limit the size of the body?
|
|
332
|
-
const data = /^application\/json$/i.test(res.headers['content-type'])
|
|
333
|
-
? await res.json()
|
|
334
|
-
: /^text-.+/i.test(res.headers['content-type'])
|
|
335
|
-
? await res.text()
|
|
336
|
-
: await res.dump()
|
|
337
|
-
throw createError(res.statusCode, { headers, data })
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
return res
|
|
341
354
|
}
|
package/lib/interceptor/cache.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from 'node:assert'
|
|
2
2
|
import { LRUCache } from 'lru-cache'
|
|
3
|
-
import
|
|
3
|
+
import { findHeader, parseCacheControl } from '../utils.js'
|
|
4
4
|
|
|
5
5
|
class CacheHandler {
|
|
6
6
|
constructor({ key, handler, store }) {
|
|
@@ -14,8 +14,8 @@ class CacheHandler {
|
|
|
14
14
|
return this.handler.onConnect(abort)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
onUpgrade(statusCode, rawHeaders, socket) {
|
|
18
|
-
return this.handler.onUpgrade(statusCode, rawHeaders, socket)
|
|
17
|
+
onUpgrade(statusCode, rawHeaders, socket, headers) {
|
|
18
|
+
return this.handler.onUpgrade(statusCode, rawHeaders, socket, headers)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
onBodySent(chunk) {
|
|
@@ -26,22 +26,13 @@ class CacheHandler {
|
|
|
26
26
|
return this.handler.onRequestSent()
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
29
|
+
onHeaders(statusCode, rawHeaders, resume, statusMessage, headers) {
|
|
30
30
|
// NOTE: Only cache 307 respones for now...
|
|
31
31
|
if (statusCode !== 307) {
|
|
32
|
-
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
32
|
+
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage, headers)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
for (let n = 0; n < rawHeaders.length; n += 2) {
|
|
37
|
-
if (
|
|
38
|
-
rawHeaders[n].length === 'cache-control'.length &&
|
|
39
|
-
rawHeaders[n].toString().toLowerCase() === 'cache-control'
|
|
40
|
-
) {
|
|
41
|
-
cacheControl = cacheControlParser.parse(rawHeaders[n + 1].toString())
|
|
42
|
-
break
|
|
43
|
-
}
|
|
44
|
-
}
|
|
35
|
+
const cacheControl = parseCacheControl(findHeader(rawHeaders, 'cache-control'))
|
|
45
36
|
|
|
46
37
|
if (
|
|
47
38
|
cacheControl &&
|
|
@@ -73,7 +64,7 @@ class CacheHandler {
|
|
|
73
64
|
}
|
|
74
65
|
}
|
|
75
66
|
|
|
76
|
-
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
67
|
+
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage, headers)
|
|
77
68
|
}
|
|
78
69
|
|
|
79
70
|
onData(chunk) {
|
package/lib/interceptor/log.js
CHANGED
|
@@ -31,13 +31,13 @@ class Handler {
|
|
|
31
31
|
})
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
onUpgrade(statusCode, rawHeaders, socket) {
|
|
34
|
+
onUpgrade(statusCode, rawHeaders, socket, headers) {
|
|
35
35
|
this.logger.debug('upstream request upgraded')
|
|
36
36
|
socket.on('close', () => {
|
|
37
37
|
this.logger.debug('upstream request socket closed')
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
-
return this.handler.onUpgrade(statusCode, rawHeaders, socket)
|
|
40
|
+
return this.handler.onUpgrade(statusCode, rawHeaders, socket, headers)
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
onBodySent(chunk) {
|
|
@@ -54,18 +54,18 @@ class Handler {
|
|
|
54
54
|
return this.handler.onRequestSent()
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
57
|
+
onHeaders(statusCode, rawHeaders, resume, statusMessage, headers = parseHeaders(rawHeaders)) {
|
|
58
58
|
this.stats.headers = performance.now() - this.stats.start
|
|
59
59
|
|
|
60
60
|
this.logger.debug(
|
|
61
61
|
{
|
|
62
|
-
ures: { statusCode, headers
|
|
62
|
+
ures: { statusCode, headers },
|
|
63
63
|
elapsedTime: this.stats.headers,
|
|
64
64
|
},
|
|
65
65
|
'upstream request response',
|
|
66
66
|
)
|
|
67
67
|
|
|
68
|
-
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
68
|
+
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage, headers)
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
onData(chunk) {
|
|
@@ -34,8 +34,8 @@ class Handler {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
onUpgrade(statusCode,
|
|
38
|
-
return this.handler.onUpgrade(statusCode,
|
|
37
|
+
onUpgrade(statusCode, rawHeaders, socket, headers) {
|
|
38
|
+
return this.handler.onUpgrade(statusCode, rawHeaders, socket, headers)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
onBodySent(chunk) {
|
|
@@ -46,16 +46,16 @@ class Handler {
|
|
|
46
46
|
return this.handler.onRequestSent()
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
onHeaders(statusCode,
|
|
49
|
+
onHeaders(statusCode, rawHeaders, resume, statusText, headers) {
|
|
50
50
|
if (redirectableStatusCodes.indexOf(statusCode) === -1) {
|
|
51
|
-
return this.handler.onHeaders(statusCode,
|
|
51
|
+
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusText, headers)
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
if (isDisturbed(this.opts.body)) {
|
|
55
55
|
throw new Error(`Disturbed request cannot be redirected.`)
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
this.location = findHeader(
|
|
58
|
+
this.location = findHeader(rawHeaders, 'location')
|
|
59
59
|
|
|
60
60
|
if (!this.location) {
|
|
61
61
|
throw new Error(`Missing redirection location .`)
|
|
@@ -65,7 +65,7 @@ class Handler {
|
|
|
65
65
|
|
|
66
66
|
if (typeof this.opts.follow === 'function') {
|
|
67
67
|
if (!this.opts.follow(this.location, this.count)) {
|
|
68
|
-
return this.handler.onHeaders(statusCode,
|
|
68
|
+
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusText, headers)
|
|
69
69
|
}
|
|
70
70
|
} else {
|
|
71
71
|
if (this.count >= this.maxCount) {
|
|
@@ -8,7 +8,7 @@ export default (dispatch) => (opts, handler) => {
|
|
|
8
8
|
|
|
9
9
|
const body = opts.body({ signal: opts.signal })
|
|
10
10
|
|
|
11
|
-
if (typeof body
|
|
11
|
+
if (typeof body?.then === 'function') {
|
|
12
12
|
body.then(
|
|
13
13
|
(body) => dispatch({ ...opts, body }, handler),
|
|
14
14
|
(err) => handler.onError(err),
|
|
@@ -27,8 +27,8 @@ class Handler {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
onUpgrade(statusCode, rawHeaders, socket) {
|
|
31
|
-
return this.handler.onUpgrade(statusCode, rawHeaders, socket)
|
|
30
|
+
onUpgrade(statusCode, rawHeaders, socket, headers) {
|
|
31
|
+
return this.handler.onUpgrade(statusCode, rawHeaders, socket, headers)
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
onBodySent(chunk) {
|
|
@@ -39,8 +39,8 @@ class Handler {
|
|
|
39
39
|
return this.handler.onRequestSent()
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
43
|
-
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
42
|
+
onHeaders(statusCode, rawHeaders, resume, statusMessage, headers) {
|
|
43
|
+
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage, headers)
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
onData(chunk) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import crypto from 'node:crypto'
|
|
2
|
+
import { findHeader } from '../utils.js'
|
|
2
3
|
|
|
3
4
|
class Handler {
|
|
4
5
|
constructor(opts, { handler, md5, length }) {
|
|
@@ -16,8 +17,8 @@ class Handler {
|
|
|
16
17
|
return this.handler.onConnect(abort)
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
onUpgrade(statusCode, rawHeaders, socket) {
|
|
20
|
-
return this.handler.onUpgrade(statusCode, rawHeaders, socket)
|
|
20
|
+
onUpgrade(statusCode, rawHeaders, socket, headers) {
|
|
21
|
+
return this.handler.onUpgrade(statusCode, rawHeaders, socket, headers)
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
onBodySent(chunk) {
|
|
@@ -51,8 +52,8 @@ class Handler {
|
|
|
51
52
|
return this.handler.onRequestSent()
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
55
|
-
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
55
|
+
onHeaders(statusCode, rawHeaders, resume, statusMessage, headers) {
|
|
56
|
+
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage, headers)
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
onData(chunk) {
|
|
@@ -74,8 +75,8 @@ export default (dispatch) => (opts, handler) => {
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
// TODO (fix): case-insensitive check?
|
|
77
|
-
const md5 = opts.headers
|
|
78
|
-
const length = opts.headers
|
|
78
|
+
const md5 = findHeader(opts.headers, 'content-md5')
|
|
79
|
+
const length = findHeader(opts.headers, 'content-length')
|
|
79
80
|
|
|
80
81
|
return md5 != null || length != null
|
|
81
82
|
? dispatch(opts, new Handler(opts, { handler, md5, length }))
|
|
@@ -14,8 +14,8 @@ class Handler {
|
|
|
14
14
|
return this.handler.onConnect(abort)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
onUpgrade(statusCode, rawHeaders, socket) {
|
|
18
|
-
return this.handler.onUpgrade(statusCode, rawHeaders, socket)
|
|
17
|
+
onUpgrade(statusCode, rawHeaders, socket, headers) {
|
|
18
|
+
return this.handler.onUpgrade(statusCode, rawHeaders, socket, headers)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
onBodySent(chunk) {
|
|
@@ -26,12 +26,12 @@ class Handler {
|
|
|
26
26
|
return this.handler.onRequestSent()
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
29
|
+
onHeaders(statusCode, rawHeaders, resume, statusMessage, headers) {
|
|
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
|
+
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage, headers)
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
onData(chunk) {
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { findHeader, parseHeaders } from '../utils.js'
|
|
2
|
+
import createHttpError from 'http-errors'
|
|
3
|
+
|
|
4
|
+
class Handler {
|
|
5
|
+
constructor(opts, { handler }) {
|
|
6
|
+
this.handler = handler
|
|
7
|
+
this.statusCode = 0
|
|
8
|
+
this.contentType = null
|
|
9
|
+
this.decoder = null
|
|
10
|
+
this.headers = null
|
|
11
|
+
this.body = null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
onConnect(abort) {
|
|
15
|
+
return this.handler.onConnect(abort)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
onUpgrade(statusCode, rawHeaders, socket, headers) {
|
|
19
|
+
return this.handler.onUpgrade(statusCode, rawHeaders, socket, headers)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
onBodySent(chunk) {
|
|
23
|
+
return this.handler.onBodySent(chunk)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
onRequestSent() {
|
|
27
|
+
return this.handler.onRequestSent()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
onHeaders(statusCode, rawHeaders, resume, statusMessage, headers = parseHeaders(rawHeaders)) {
|
|
31
|
+
if (statusCode >= 400) {
|
|
32
|
+
this.statusCode = statusCode
|
|
33
|
+
this.headers = headers
|
|
34
|
+
this.contentType = findHeader(rawHeaders, 'content-type')
|
|
35
|
+
if (this.contentType === 'application/json' || this.contentType === 'text/plain') {
|
|
36
|
+
this.decoder = new TextDecoder('utf-8')
|
|
37
|
+
this.body = ''
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage, headers)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
onData(chunk) {
|
|
45
|
+
if (this.statusCode) {
|
|
46
|
+
if (this.decoder) {
|
|
47
|
+
// TODO (fix): Limit body size?
|
|
48
|
+
this.body += this.decoder.decode(chunk, { stream: true })
|
|
49
|
+
}
|
|
50
|
+
return true
|
|
51
|
+
} else {
|
|
52
|
+
return this.handler.onData(chunk)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
onComplete(rawTrailers) {
|
|
57
|
+
this.onFinally(null, rawTrailers)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
onError(err) {
|
|
61
|
+
this.onFinally(err, null)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
onFinally(err, rawTrailers) {
|
|
65
|
+
if (this.statusCode) {
|
|
66
|
+
if (this.decoder != null) {
|
|
67
|
+
this.body += this.decoder.decode(undefined, { stream: false })
|
|
68
|
+
if (this.contentType === 'application/json') {
|
|
69
|
+
this.body = JSON.parse(this.body)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const stackTraceLimit = Error.stackTraceLimit
|
|
74
|
+
Error.stackTraceLimit = 0
|
|
75
|
+
try {
|
|
76
|
+
this.handler.onError(
|
|
77
|
+
createHttpError(this.statusCode, { headers: this.headers, body: this.body }),
|
|
78
|
+
)
|
|
79
|
+
} finally {
|
|
80
|
+
Error.stackTraceLimit = stackTraceLimit
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
this.decoder = null
|
|
84
|
+
this.contentType = null
|
|
85
|
+
this.body = null
|
|
86
|
+
} else if (err) {
|
|
87
|
+
this.handler.onError(err)
|
|
88
|
+
} else {
|
|
89
|
+
this.handler.onComplete(rawTrailers)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
this.handler = null
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default (dispatch) => (opts, handler) => dispatch(opts, new Handler(opts, { handler }))
|
|
@@ -6,18 +6,16 @@ class Handler {
|
|
|
6
6
|
this.dispatch = dispatch
|
|
7
7
|
this.handler = handler
|
|
8
8
|
this.opts = opts
|
|
9
|
-
this.abort = null
|
|
10
|
-
this.aborted = false
|
|
11
|
-
this.reason = null
|
|
12
|
-
|
|
13
|
-
this.retryCount = 0
|
|
14
|
-
this.retryPromise = null
|
|
15
9
|
|
|
10
|
+
this.count = 0
|
|
16
11
|
this.pos = 0
|
|
17
12
|
this.end = null
|
|
18
13
|
this.error = null
|
|
19
14
|
this.etag = null
|
|
20
15
|
|
|
16
|
+
this.reason = null
|
|
17
|
+
this.aborted = false
|
|
18
|
+
|
|
21
19
|
this.handler.onConnect((reason) => {
|
|
22
20
|
this.aborted = true
|
|
23
21
|
if (this.abort) {
|
|
@@ -36,8 +34,8 @@ class Handler {
|
|
|
36
34
|
}
|
|
37
35
|
}
|
|
38
36
|
|
|
39
|
-
onUpgrade(statusCode, rawHeaders, socket) {
|
|
40
|
-
return this.handler.onUpgrade(statusCode, rawHeaders, socket)
|
|
37
|
+
onUpgrade(statusCode, rawHeaders, socket, headers) {
|
|
38
|
+
return this.handler.onUpgrade(statusCode, rawHeaders, socket, headers)
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
onBodySent(chunk) {
|
|
@@ -48,7 +46,7 @@ class Handler {
|
|
|
48
46
|
return this.handler.onRequestSent()
|
|
49
47
|
}
|
|
50
48
|
|
|
51
|
-
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
49
|
+
onHeaders(statusCode, rawHeaders, resume, statusMessage, headers) {
|
|
52
50
|
const etag = findHeader(rawHeaders, 'etag')
|
|
53
51
|
|
|
54
52
|
if (this.resume) {
|
|
@@ -82,7 +80,13 @@ class Handler {
|
|
|
82
80
|
if (statusCode === 206) {
|
|
83
81
|
const contentRange = parseContentRange(findHeader(rawHeaders, 'content-range'))
|
|
84
82
|
if (!contentRange) {
|
|
85
|
-
return this.handler.onHeaders(
|
|
83
|
+
return this.handler.onHeaders(
|
|
84
|
+
statusCode,
|
|
85
|
+
rawHeaders,
|
|
86
|
+
() => this.resume(),
|
|
87
|
+
statusMessage,
|
|
88
|
+
headers,
|
|
89
|
+
)
|
|
86
90
|
}
|
|
87
91
|
|
|
88
92
|
const { start, size, end = size } = contentRange
|
|
@@ -102,7 +106,14 @@ class Handler {
|
|
|
102
106
|
|
|
103
107
|
this.etag = etag
|
|
104
108
|
this.resume = resume
|
|
105
|
-
|
|
109
|
+
|
|
110
|
+
return this.handler.onHeaders(
|
|
111
|
+
statusCode,
|
|
112
|
+
rawHeaders,
|
|
113
|
+
() => this.resume(),
|
|
114
|
+
statusMessage,
|
|
115
|
+
headers,
|
|
116
|
+
)
|
|
106
117
|
}
|
|
107
118
|
|
|
108
119
|
onData(chunk) {
|
|
@@ -116,31 +127,15 @@ class Handler {
|
|
|
116
127
|
}
|
|
117
128
|
|
|
118
129
|
onError(err) {
|
|
119
|
-
if (
|
|
130
|
+
if (this.aborted || !this.etag || isDisturbed(this.opts.body)) {
|
|
120
131
|
return this.handler.onError(err)
|
|
121
132
|
}
|
|
122
133
|
|
|
123
|
-
const retryPromise = retryFn(err, this.
|
|
134
|
+
const retryPromise = retryFn(err, this.count++, this.opts)
|
|
124
135
|
if (retryPromise == null) {
|
|
125
136
|
return this.handler.onError(err)
|
|
126
137
|
}
|
|
127
138
|
|
|
128
|
-
retryPromise
|
|
129
|
-
.then(() => {
|
|
130
|
-
if (!this.aborted) {
|
|
131
|
-
try {
|
|
132
|
-
this.dispatch(this.opts, this)
|
|
133
|
-
} catch (err2) {
|
|
134
|
-
this.handler.onError(new AggregateError([err, err2]))
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
})
|
|
138
|
-
.catch((err) => {
|
|
139
|
-
if (!this.aborted) {
|
|
140
|
-
this.handler.onError(err)
|
|
141
|
-
}
|
|
142
|
-
})
|
|
143
|
-
|
|
144
139
|
this.error = err
|
|
145
140
|
this.opts = {
|
|
146
141
|
...this.opts,
|
|
@@ -152,6 +147,18 @@ class Handler {
|
|
|
152
147
|
}
|
|
153
148
|
|
|
154
149
|
this.opts.logger?.debug('retrying response body')
|
|
150
|
+
|
|
151
|
+
retryPromise
|
|
152
|
+
.then(() => {
|
|
153
|
+
if (!this.aborted) {
|
|
154
|
+
this.dispatch(this.opts, this)
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
.catch((err) => {
|
|
158
|
+
if (!this.aborted) {
|
|
159
|
+
this.handler.onError(err)
|
|
160
|
+
}
|
|
161
|
+
})
|
|
155
162
|
}
|
|
156
163
|
}
|
|
157
164
|
|
|
@@ -5,13 +5,12 @@ class Handler {
|
|
|
5
5
|
this.dispatch = dispatch
|
|
6
6
|
this.handler = handler
|
|
7
7
|
this.opts = opts
|
|
8
|
-
this.abort = null
|
|
9
|
-
this.aborted = false
|
|
10
|
-
this.reason = null
|
|
11
|
-
this.statusCode = 0
|
|
12
8
|
|
|
13
|
-
this.
|
|
14
|
-
this.
|
|
9
|
+
this.hasBody = false
|
|
10
|
+
this.count = 0
|
|
11
|
+
|
|
12
|
+
this.reason = null
|
|
13
|
+
this.aborted = false
|
|
15
14
|
|
|
16
15
|
this.handler.onConnect((reason) => {
|
|
17
16
|
this.aborted = true
|
|
@@ -31,8 +30,8 @@ class Handler {
|
|
|
31
30
|
}
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
onUpgrade(statusCode, rawHeaders, socket) {
|
|
35
|
-
return this.handler.onUpgrade(statusCode, rawHeaders, socket)
|
|
33
|
+
onUpgrade(statusCode, rawHeaders, socket, headers) {
|
|
34
|
+
return this.handler.onUpgrade(statusCode, rawHeaders, socket, headers)
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
onBodySent(chunk) {
|
|
@@ -43,12 +42,12 @@ class Handler {
|
|
|
43
42
|
return this.handler.onRequestSent()
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
47
|
-
this.statusCode
|
|
48
|
-
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
45
|
+
onHeaders(statusCode, rawHeaders, resume, statusMessage, headers) {
|
|
46
|
+
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage, headers)
|
|
49
47
|
}
|
|
50
48
|
|
|
51
49
|
onData(chunk) {
|
|
50
|
+
this.hasBody = true
|
|
52
51
|
return this.handler.onData(chunk)
|
|
53
52
|
}
|
|
54
53
|
|
|
@@ -57,23 +56,21 @@ class Handler {
|
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
onError(err) {
|
|
60
|
-
if (this.aborted || this.
|
|
59
|
+
if (this.aborted || this.hasBody || isDisturbed(this.opts.body)) {
|
|
61
60
|
return this.handler.onError(err)
|
|
62
61
|
}
|
|
63
62
|
|
|
64
|
-
const retryPromise = retryFn(err, this.
|
|
63
|
+
const retryPromise = retryFn(err, this.count++, this.opts)
|
|
65
64
|
if (retryPromise == null) {
|
|
66
65
|
return this.handler.onError(err)
|
|
67
66
|
}
|
|
68
67
|
|
|
68
|
+
this.opts.logger?.debug('retrying response')
|
|
69
|
+
|
|
69
70
|
retryPromise
|
|
70
71
|
.then(() => {
|
|
71
72
|
if (!this.aborted) {
|
|
72
|
-
|
|
73
|
-
this.dispatch(this.opts, this)
|
|
74
|
-
} catch (err2) {
|
|
75
|
-
this.handler.onError(new AggregateError([err, err2]))
|
|
76
|
-
}
|
|
73
|
+
this.dispatch(this.opts, this)
|
|
77
74
|
}
|
|
78
75
|
})
|
|
79
76
|
.catch((err) => {
|
|
@@ -81,12 +78,11 @@ class Handler {
|
|
|
81
78
|
this.handler.onError(err)
|
|
82
79
|
}
|
|
83
80
|
})
|
|
84
|
-
|
|
85
|
-
this.opts.logger?.debug('retrying response')
|
|
86
81
|
}
|
|
87
82
|
}
|
|
88
83
|
|
|
89
|
-
export default (dispatch) => (opts, handler) =>
|
|
90
|
-
|
|
84
|
+
export default (dispatch) => (opts, handler) => {
|
|
85
|
+
return opts.retry
|
|
91
86
|
? dispatch(opts, new Handler(opts, { handler, dispatch }))
|
|
92
87
|
: dispatch(opts, handler)
|
|
88
|
+
}
|
package/lib/utils.js
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import tp from 'node:timers/promises'
|
|
2
|
+
import cacheControlParser from 'cache-control-parser'
|
|
3
|
+
|
|
4
|
+
export function parseCacheControl(str) {
|
|
5
|
+
return str ? cacheControlParser.parse(str) : null
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const lowerCaseCache = new Map()
|
|
9
|
+
export function toLowerCase(val) {
|
|
10
|
+
let ret = lowerCaseCache.get(val)
|
|
11
|
+
if (ret === undefined) {
|
|
12
|
+
ret = val.toLowerCase()
|
|
13
|
+
lowerCaseCache.set(val, ret)
|
|
14
|
+
}
|
|
15
|
+
return ret
|
|
16
|
+
}
|
|
2
17
|
|
|
3
18
|
export function isDisturbed(body) {
|
|
4
19
|
if (
|
|
@@ -45,15 +60,31 @@ export function parseContentRange(range) {
|
|
|
45
60
|
return { start, end: end ? end + 1 : size, size }
|
|
46
61
|
}
|
|
47
62
|
|
|
48
|
-
export function findHeader(
|
|
63
|
+
export function findHeader(headers, name) {
|
|
49
64
|
const len = name.length
|
|
50
65
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
66
|
+
if (Array.isArray(headers)) {
|
|
67
|
+
for (let i = 0; i < headers.length; i += 2) {
|
|
68
|
+
const key = headers[i + 0]
|
|
69
|
+
if (key.length === len && toLowerCase(key.toString()) === name) {
|
|
70
|
+
return headers[i + 1].toString()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} else if (headers != null) {
|
|
74
|
+
{
|
|
75
|
+
const val = headers[name]
|
|
76
|
+
if (val !== undefined) {
|
|
77
|
+
return val
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
for (const key of Object.keys(headers)) {
|
|
82
|
+
if (key.length === len && toLowerCase(key) === name) {
|
|
83
|
+
return headers[key].toString()
|
|
84
|
+
}
|
|
55
85
|
}
|
|
56
86
|
}
|
|
87
|
+
|
|
57
88
|
return null
|
|
58
89
|
}
|
|
59
90
|
|
|
@@ -178,18 +209,24 @@ export function parseOrigin(url) {
|
|
|
178
209
|
return url
|
|
179
210
|
}
|
|
180
211
|
|
|
181
|
-
export function parseHeaders(
|
|
182
|
-
for (let i = 0; i <
|
|
183
|
-
const key =
|
|
212
|
+
export function parseHeaders(headers, obj = {}) {
|
|
213
|
+
for (let i = 0; i < headers.length; i += 2) {
|
|
214
|
+
const key = toLowerCase(headers[i].toString())
|
|
215
|
+
|
|
184
216
|
let val = obj[key]
|
|
185
217
|
if (!val) {
|
|
186
|
-
|
|
218
|
+
val = headers[i + 1]
|
|
219
|
+
if (typeof val === 'string') {
|
|
220
|
+
obj[key] = val
|
|
221
|
+
} else {
|
|
222
|
+
obj[key] = Array.isArray(val) ? val.map((x) => x.toString()) : val.toString()
|
|
223
|
+
}
|
|
187
224
|
} else {
|
|
188
225
|
if (!Array.isArray(val)) {
|
|
189
226
|
val = [val]
|
|
190
227
|
obj[key] = val
|
|
191
228
|
}
|
|
192
|
-
val.push(
|
|
229
|
+
val.push(headers[i + 1].toString())
|
|
193
230
|
}
|
|
194
231
|
}
|
|
195
232
|
return obj
|
package/package.json
CHANGED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { parseHeaders, isDisturbed, retry as retryFn } from '../utils.js'
|
|
2
|
-
import createError from 'http-errors'
|
|
3
|
-
|
|
4
|
-
class Handler {
|
|
5
|
-
constructor(opts, { dispatch, handler }) {
|
|
6
|
-
this.dispatch = dispatch
|
|
7
|
-
this.handler = handler
|
|
8
|
-
this.opts = opts
|
|
9
|
-
this.abort = null
|
|
10
|
-
this.aborted = false
|
|
11
|
-
this.reason = null
|
|
12
|
-
|
|
13
|
-
this.retryCount = 0
|
|
14
|
-
this.retryPromise = null
|
|
15
|
-
|
|
16
|
-
this.handler.onConnect((reason) => {
|
|
17
|
-
this.aborted = true
|
|
18
|
-
if (this.abort) {
|
|
19
|
-
this.abort(reason)
|
|
20
|
-
} else {
|
|
21
|
-
this.reason = reason
|
|
22
|
-
}
|
|
23
|
-
})
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
onConnect(abort) {
|
|
27
|
-
if (this.aborted) {
|
|
28
|
-
abort(this.reason)
|
|
29
|
-
} else {
|
|
30
|
-
this.abort = abort
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
onUpgrade(statusCode, rawHeaders, socket) {
|
|
35
|
-
return this.handler.onUpgrade(statusCode, rawHeaders, socket)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
onBodySent(chunk) {
|
|
39
|
-
return this.handler.onBodySent(chunk)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
onRequestSent() {
|
|
43
|
-
return this.handler.onRequestSent()
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
47
|
-
if (statusCode < 400) {
|
|
48
|
-
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const err = createError(statusCode, { headers: parseHeaders(rawHeaders) })
|
|
52
|
-
|
|
53
|
-
const retryPromise = retryFn(err, this.retryCount++, this.opts)
|
|
54
|
-
if (retryPromise == null) {
|
|
55
|
-
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
retryPromise.catch(() => {})
|
|
59
|
-
|
|
60
|
-
this.retryPromise = retryPromise
|
|
61
|
-
|
|
62
|
-
this.abort(err)
|
|
63
|
-
|
|
64
|
-
return false
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
onData(chunk) {
|
|
68
|
-
return this.handler.onData(chunk)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
onComplete(rawTrailers) {
|
|
72
|
-
return this.handler.onComplete(rawTrailers)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
onError(err) {
|
|
76
|
-
if (this.retryPromise == null || this.aborted || isDisturbed(this.opts.body)) {
|
|
77
|
-
return this.handler.onError(err)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
this.retryPromise
|
|
81
|
-
.then(() => {
|
|
82
|
-
if (!this.aborted) {
|
|
83
|
-
try {
|
|
84
|
-
this.dispatch(this.opts, this)
|
|
85
|
-
} catch (err2) {
|
|
86
|
-
this.handler.onError(new AggregateError([err, err2]))
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
.catch((err) => {
|
|
91
|
-
if (!this.aborted) {
|
|
92
|
-
this.handler.onError(err)
|
|
93
|
-
}
|
|
94
|
-
})
|
|
95
|
-
this.retryPromise = null
|
|
96
|
-
|
|
97
|
-
this.opts.logger?.debug('retrying response status')
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export default (dispatch) => (opts, handler) =>
|
|
102
|
-
opts.idempotent && opts.retry
|
|
103
|
-
? dispatch(opts, new Handler(opts, { handler, dispatch }))
|
|
104
|
-
: dispatch(opts, handler)
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
class Handler {
|
|
2
|
-
constructor(opts, { handler }) {
|
|
3
|
-
this.handler = handler
|
|
4
|
-
this.signal = opts.signal
|
|
5
|
-
this.abort = null
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
onConnect(abort) {
|
|
9
|
-
if (this.signal.aborted) {
|
|
10
|
-
abort(this.signal.reason)
|
|
11
|
-
} else {
|
|
12
|
-
this.abort = () => abort(this.signal.reason)
|
|
13
|
-
this.signal.addEventListener('abort', this.abort)
|
|
14
|
-
|
|
15
|
-
this.handler.onConnect(abort)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
onUpgrade(statusCode, rawHeaders, socket) {
|
|
20
|
-
return this.handler.onUpgrade(statusCode, rawHeaders, socket)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
onBodySent(chunk) {
|
|
24
|
-
return this.handler.onBodySent(chunk)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
onRequestSent() {
|
|
28
|
-
return this.handler.onRequestSent()
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
32
|
-
return this.handler.onHeaders(statusCode, rawHeaders, resume, statusMessage)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
onData(chunk) {
|
|
36
|
-
return this.handler.onData(chunk)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
onComplete(rawTrailers) {
|
|
40
|
-
if (this.abort) {
|
|
41
|
-
this.signal.removeEventListener('abort', this.abort)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return this.handler.onComplete(rawTrailers)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
onError(err) {
|
|
48
|
-
if (this.abort) {
|
|
49
|
-
this.signal.removeEventListener('abort', this.abort)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return this.handler.onError(err)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export default (dispatch) => (opts, handler) =>
|
|
57
|
-
opts.signal ? dispatch(opts, new Handler(opts, { handler })) : dispatch(opts, handler)
|