undici 5.3.0 → 5.4.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/README.md +9 -0
- package/docs/api/MockPool.md +1 -0
- package/lib/client.js +5 -0
- package/lib/fetch/constants.js +0 -31
- package/lib/fetch/formdata.js +4 -4
- package/lib/fetch/headers.js +8 -38
- package/lib/fetch/request.js +5 -6
- package/lib/fetch/response.js +6 -31
- package/lib/mock/mock-interceptor.js +8 -3
- package/lib/mock/mock-utils.js +8 -4
- package/package.json +4 -4
- package/types/dispatcher.d.ts +1 -1
- package/types/mock-interceptor.d.ts +3 -1
package/README.md
CHANGED
|
@@ -288,6 +288,15 @@ const headers = await fetch(url)
|
|
|
288
288
|
.then(res => res.headers)
|
|
289
289
|
```
|
|
290
290
|
|
|
291
|
+
##### Forbidden and Safelisted Header Names
|
|
292
|
+
|
|
293
|
+
* https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
|
|
294
|
+
* https://fetch.spec.whatwg.org/#forbidden-header-name
|
|
295
|
+
* https://fetch.spec.whatwg.org/#forbidden-response-header-name
|
|
296
|
+
* https://github.com/wintercg/fetch/issues/6
|
|
297
|
+
|
|
298
|
+
The [Fetch Standard](https://fetch.spec.whatwg.org) requires implementations to exclude certain headers from requests and responses. In browser environments, some headers are forbidden so the user agent remains in full control over them. In Undici, these constraints are removed to give more control to the user.
|
|
299
|
+
|
|
291
300
|
### `undici.upgrade([url, options]): Promise`
|
|
292
301
|
|
|
293
302
|
Upgrade to a different protocol. See [MDN - HTTP - Protocol upgrade mechanism](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism) for more details.
|
package/docs/api/MockPool.md
CHANGED
|
@@ -57,6 +57,7 @@ Returns: `MockInterceptor` corresponding to the input options.
|
|
|
57
57
|
* **method** `string | RegExp | (method: string) => boolean` - a matcher for the HTTP request method.
|
|
58
58
|
* **body** `string | RegExp | (body: string) => boolean` - (optional) - a matcher for the HTTP request body.
|
|
59
59
|
* **headers** `Record<string, string | RegExp | (body: string) => boolean`> - (optional) - a matcher for the HTTP request headers. To be intercepted, a request must match all defined headers. Extra headers not defined here may (or may not) be included in the request and do not affect the interception in any way.
|
|
60
|
+
* **query** `Record<string, any> | null` - (optional) - a matcher for the HTTP request query string params.
|
|
60
61
|
|
|
61
62
|
### Return: `MockInterceptor`
|
|
62
63
|
|
package/lib/client.js
CHANGED
|
@@ -873,6 +873,11 @@ class Parser {
|
|
|
873
873
|
// have been queued since then.
|
|
874
874
|
util.destroy(socket, new InformationalError('reset'))
|
|
875
875
|
return constants.ERROR.PAUSED
|
|
876
|
+
} else if (client[kPipelining] === 1) {
|
|
877
|
+
// We must wait a full event loop cycle to reuse this socket to make sure
|
|
878
|
+
// that non-spec compliant servers are not closing the connection even if they
|
|
879
|
+
// said they won't.
|
|
880
|
+
setImmediate(resume, client)
|
|
876
881
|
} else {
|
|
877
882
|
resume(client)
|
|
878
883
|
}
|
package/lib/fetch/constants.js
CHANGED
|
@@ -1,28 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const forbiddenHeaderNames = [
|
|
4
|
-
'accept-charset',
|
|
5
|
-
'accept-encoding',
|
|
6
|
-
'access-control-request-headers',
|
|
7
|
-
'access-control-request-method',
|
|
8
|
-
'connection',
|
|
9
|
-
'content-length',
|
|
10
|
-
'cookie',
|
|
11
|
-
'cookie2',
|
|
12
|
-
'date',
|
|
13
|
-
'dnt',
|
|
14
|
-
'expect',
|
|
15
|
-
'host',
|
|
16
|
-
'keep-alive',
|
|
17
|
-
'origin',
|
|
18
|
-
'referer',
|
|
19
|
-
'te',
|
|
20
|
-
'trailer',
|
|
21
|
-
'transfer-encoding',
|
|
22
|
-
'upgrade',
|
|
23
|
-
'via'
|
|
24
|
-
]
|
|
25
|
-
|
|
26
3
|
const corsSafeListedMethods = ['GET', 'HEAD', 'POST']
|
|
27
4
|
|
|
28
5
|
const nullBodyStatus = [101, 204, 205, 304]
|
|
@@ -58,9 +35,6 @@ const requestCache = [
|
|
|
58
35
|
'only-if-cached'
|
|
59
36
|
]
|
|
60
37
|
|
|
61
|
-
// https://fetch.spec.whatwg.org/#forbidden-response-header-name
|
|
62
|
-
const forbiddenResponseHeaderNames = ['set-cookie', 'set-cookie2']
|
|
63
|
-
|
|
64
38
|
const requestBodyHeader = [
|
|
65
39
|
'content-encoding',
|
|
66
40
|
'content-language',
|
|
@@ -86,12 +60,8 @@ const subresource = [
|
|
|
86
60
|
''
|
|
87
61
|
]
|
|
88
62
|
|
|
89
|
-
const corsSafeListedResponseHeaderNames = [] // TODO
|
|
90
|
-
|
|
91
63
|
module.exports = {
|
|
92
64
|
subresource,
|
|
93
|
-
forbiddenResponseHeaderNames,
|
|
94
|
-
corsSafeListedResponseHeaderNames,
|
|
95
65
|
forbiddenMethods,
|
|
96
66
|
requestBodyHeader,
|
|
97
67
|
referrerPolicy,
|
|
@@ -99,7 +69,6 @@ module.exports = {
|
|
|
99
69
|
requestMode,
|
|
100
70
|
requestCredentials,
|
|
101
71
|
requestCache,
|
|
102
|
-
forbiddenHeaderNames,
|
|
103
72
|
redirectStatus,
|
|
104
73
|
corsSafeListedMethods,
|
|
105
74
|
nullBodyStatus,
|
package/lib/fetch/formdata.js
CHANGED
|
@@ -243,8 +243,8 @@ function makeEntry (name, value, filename) {
|
|
|
243
243
|
// object, representing the same bytes, whose name attribute value is "blob".
|
|
244
244
|
if (isBlobLike(value) && !isFileLike(value)) {
|
|
245
245
|
value = value instanceof Blob
|
|
246
|
-
? new File([value], 'blob')
|
|
247
|
-
: new FileLike(value, 'blob')
|
|
246
|
+
? new File([value], 'blob', value)
|
|
247
|
+
: new FileLike(value, 'blob', value)
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
// 4. If value is (now) a File object and filename is given, then set value to a
|
|
@@ -256,8 +256,8 @@ function makeEntry (name, value, filename) {
|
|
|
256
256
|
// creating one more File instance doesn't make much sense....
|
|
257
257
|
if (isFileLike(value) && filename != null) {
|
|
258
258
|
value = value instanceof File
|
|
259
|
-
? new File([value], filename)
|
|
260
|
-
: new FileLike(value, filename)
|
|
259
|
+
? new File([value], filename, value)
|
|
260
|
+
: new FileLike(value, filename, value)
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
// 5. Set entry’s value to value.
|
package/lib/fetch/headers.js
CHANGED
|
@@ -6,10 +6,6 @@ const { validateHeaderName, validateHeaderValue } = require('http')
|
|
|
6
6
|
const { kHeadersList } = require('../core/symbols')
|
|
7
7
|
const { kGuard } = require('./symbols')
|
|
8
8
|
const { kEnumerableProperty } = require('../core/util')
|
|
9
|
-
const {
|
|
10
|
-
forbiddenHeaderNames,
|
|
11
|
-
forbiddenResponseHeaderNames
|
|
12
|
-
} = require('./constants')
|
|
13
9
|
|
|
14
10
|
const kHeadersMap = Symbol('headers map')
|
|
15
11
|
const kHeadersSortedMap = Symbol('headers map sorted')
|
|
@@ -115,6 +111,11 @@ class HeadersList {
|
|
|
115
111
|
}
|
|
116
112
|
}
|
|
117
113
|
|
|
114
|
+
clear () {
|
|
115
|
+
this[kHeadersMap].clear()
|
|
116
|
+
this[kHeadersSortedMap] = null
|
|
117
|
+
}
|
|
118
|
+
|
|
118
119
|
append (name, value) {
|
|
119
120
|
this[kHeadersSortedMap] = null
|
|
120
121
|
|
|
@@ -211,22 +212,11 @@ class Headers {
|
|
|
211
212
|
)
|
|
212
213
|
}
|
|
213
214
|
|
|
214
|
-
|
|
215
|
-
|
|
215
|
+
// Note: undici does not implement forbidden header names
|
|
216
216
|
if (this[kGuard] === 'immutable') {
|
|
217
217
|
throw new TypeError('immutable')
|
|
218
|
-
} else if (
|
|
219
|
-
this[kGuard] === 'request' &&
|
|
220
|
-
forbiddenHeaderNames.includes(normalizedName)
|
|
221
|
-
) {
|
|
222
|
-
return
|
|
223
218
|
} else if (this[kGuard] === 'request-no-cors') {
|
|
224
219
|
// TODO
|
|
225
|
-
} else if (
|
|
226
|
-
this[kGuard] === 'response' &&
|
|
227
|
-
forbiddenResponseHeaderNames.includes(normalizedName)
|
|
228
|
-
) {
|
|
229
|
-
return
|
|
230
220
|
}
|
|
231
221
|
|
|
232
222
|
return this[kHeadersList].append(String(name), String(value))
|
|
@@ -244,22 +234,11 @@ class Headers {
|
|
|
244
234
|
)
|
|
245
235
|
}
|
|
246
236
|
|
|
247
|
-
|
|
248
|
-
|
|
237
|
+
// Note: undici does not implement forbidden header names
|
|
249
238
|
if (this[kGuard] === 'immutable') {
|
|
250
239
|
throw new TypeError('immutable')
|
|
251
|
-
} else if (
|
|
252
|
-
this[kGuard] === 'request' &&
|
|
253
|
-
forbiddenHeaderNames.includes(normalizedName)
|
|
254
|
-
) {
|
|
255
|
-
return
|
|
256
240
|
} else if (this[kGuard] === 'request-no-cors') {
|
|
257
241
|
// TODO
|
|
258
|
-
} else if (
|
|
259
|
-
this[kGuard] === 'response' &&
|
|
260
|
-
forbiddenResponseHeaderNames.includes(normalizedName)
|
|
261
|
-
) {
|
|
262
|
-
return
|
|
263
242
|
}
|
|
264
243
|
|
|
265
244
|
return this[kHeadersList].delete(String(name))
|
|
@@ -307,20 +286,11 @@ class Headers {
|
|
|
307
286
|
)
|
|
308
287
|
}
|
|
309
288
|
|
|
289
|
+
// Note: undici does not implement forbidden header names
|
|
310
290
|
if (this[kGuard] === 'immutable') {
|
|
311
291
|
throw new TypeError('immutable')
|
|
312
|
-
} else if (
|
|
313
|
-
this[kGuard] === 'request' &&
|
|
314
|
-
forbiddenHeaderNames.includes(String(name).toLocaleLowerCase())
|
|
315
|
-
) {
|
|
316
|
-
return
|
|
317
292
|
} else if (this[kGuard] === 'request-no-cors') {
|
|
318
293
|
// TODO
|
|
319
|
-
} else if (
|
|
320
|
-
this[kGuard] === 'response' &&
|
|
321
|
-
forbiddenResponseHeaderNames.includes(String(name).toLocaleLowerCase())
|
|
322
|
-
) {
|
|
323
|
-
return
|
|
324
294
|
}
|
|
325
295
|
|
|
326
296
|
return this[kHeadersList].set(String(name), String(value))
|
package/lib/fetch/request.js
CHANGED
|
@@ -384,8 +384,8 @@ class Request {
|
|
|
384
384
|
// Realm, whose header list is request’s header list and guard is
|
|
385
385
|
// "request".
|
|
386
386
|
this[kHeaders] = new Headers()
|
|
387
|
-
this[kHeaders][kGuard] = 'request'
|
|
388
387
|
this[kHeaders][kHeadersList] = request.headersList
|
|
388
|
+
this[kHeaders][kGuard] = 'request'
|
|
389
389
|
this[kHeaders][kRealm] = this[kRealm]
|
|
390
390
|
|
|
391
391
|
// 31. If this’s request’s mode is "no-cors", then:
|
|
@@ -406,7 +406,7 @@ class Request {
|
|
|
406
406
|
if (Object.keys(init).length !== 0) {
|
|
407
407
|
// 1. Let headers be a copy of this’s headers and its associated header
|
|
408
408
|
// list.
|
|
409
|
-
let headers = new Headers(this
|
|
409
|
+
let headers = new Headers(this[kHeaders])
|
|
410
410
|
|
|
411
411
|
// 2. If init["headers"] exists, then set headers to init["headers"].
|
|
412
412
|
if (init.headers !== undefined) {
|
|
@@ -414,18 +414,17 @@ class Request {
|
|
|
414
414
|
}
|
|
415
415
|
|
|
416
416
|
// 3. Empty this’s headers’s header list.
|
|
417
|
-
this[
|
|
418
|
-
this[kHeaders][kHeadersList] = this[kState].headersList
|
|
417
|
+
this[kHeaders][kHeadersList].clear()
|
|
419
418
|
|
|
420
419
|
// 4. If headers is a Headers object, then for each header in its header
|
|
421
420
|
// list, append header’s name/header’s value to this’s headers.
|
|
422
421
|
if (headers.constructor.name === 'Headers') {
|
|
423
|
-
for (const [key, val] of headers
|
|
422
|
+
for (const [key, val] of headers) {
|
|
424
423
|
this[kHeaders].append(key, val)
|
|
425
424
|
}
|
|
426
425
|
} else {
|
|
427
426
|
// 5. Otherwise, fill this’s headers with headers.
|
|
428
|
-
fillHeaders(this[
|
|
427
|
+
fillHeaders(this[kHeaders], headers)
|
|
429
428
|
}
|
|
430
429
|
}
|
|
431
430
|
|
package/lib/fetch/response.js
CHANGED
|
@@ -8,9 +8,7 @@ const { kEnumerableProperty } = util
|
|
|
8
8
|
const { responseURL, isValidReasonPhrase, toUSVString, isCancelled, isAborted, serializeJavascriptValueToJSONString } = require('./util')
|
|
9
9
|
const {
|
|
10
10
|
redirectStatus,
|
|
11
|
-
nullBodyStatus
|
|
12
|
-
forbiddenResponseHeaderNames,
|
|
13
|
-
corsSafeListedResponseHeaderNames
|
|
11
|
+
nullBodyStatus
|
|
14
12
|
} = require('./constants')
|
|
15
13
|
const { kState, kHeaders, kGuard, kRealm } = require('./symbols')
|
|
16
14
|
const { kHeadersList } = require('../core/symbols')
|
|
@@ -380,28 +378,6 @@ function makeFilteredResponse (response, state) {
|
|
|
380
378
|
})
|
|
381
379
|
}
|
|
382
380
|
|
|
383
|
-
function makeFilteredHeadersList (headersList, filter) {
|
|
384
|
-
return new Proxy(headersList, {
|
|
385
|
-
get (target, prop) {
|
|
386
|
-
// Override methods used by Headers class.
|
|
387
|
-
if (prop === 'get' || prop === 'has') {
|
|
388
|
-
const defaultReturn = prop === 'has' ? false : null
|
|
389
|
-
return (name) => filter(name) ? target[prop](name) : defaultReturn
|
|
390
|
-
} else if (prop === Symbol.iterator) {
|
|
391
|
-
return function * () {
|
|
392
|
-
for (const entry of target) {
|
|
393
|
-
if (filter(entry[0])) {
|
|
394
|
-
yield entry
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
} else {
|
|
399
|
-
return target[prop]
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
})
|
|
403
|
-
}
|
|
404
|
-
|
|
405
381
|
// https://fetch.spec.whatwg.org/#concept-filtered-response
|
|
406
382
|
function filterResponse (response, type) {
|
|
407
383
|
// Set response to the following filtered response with response as its
|
|
@@ -411,12 +387,10 @@ function filterResponse (response, type) {
|
|
|
411
387
|
// and header list excludes any headers in internal response’s header list
|
|
412
388
|
// whose name is a forbidden response-header name.
|
|
413
389
|
|
|
390
|
+
// Note: undici does not implement forbidden response-header names
|
|
414
391
|
return makeFilteredResponse(response, {
|
|
415
392
|
type: 'basic',
|
|
416
|
-
headersList:
|
|
417
|
-
response.headersList,
|
|
418
|
-
(name) => !forbiddenResponseHeaderNames.includes(name.toLowerCase())
|
|
419
|
-
)
|
|
393
|
+
headersList: response.headersList
|
|
420
394
|
})
|
|
421
395
|
} else if (type === 'cors') {
|
|
422
396
|
// A CORS filtered response is a filtered response whose type is "cors"
|
|
@@ -424,9 +398,10 @@ function filterResponse (response, type) {
|
|
|
424
398
|
// list whose name is not a CORS-safelisted response-header name, given
|
|
425
399
|
// internal response’s CORS-exposed header-name list.
|
|
426
400
|
|
|
401
|
+
// Note: undici does not implement CORS-safelisted response-header names
|
|
427
402
|
return makeFilteredResponse(response, {
|
|
428
403
|
type: 'cors',
|
|
429
|
-
headersList:
|
|
404
|
+
headersList: response.headersList
|
|
430
405
|
})
|
|
431
406
|
} else if (type === 'opaque') {
|
|
432
407
|
// An opaque filtered response is a filtered response whose type is
|
|
@@ -449,7 +424,7 @@ function filterResponse (response, type) {
|
|
|
449
424
|
type: 'opaqueredirect',
|
|
450
425
|
status: 0,
|
|
451
426
|
statusText: '',
|
|
452
|
-
headersList:
|
|
427
|
+
headersList: [],
|
|
453
428
|
body: null
|
|
454
429
|
})
|
|
455
430
|
} else {
|
|
@@ -10,6 +10,7 @@ const {
|
|
|
10
10
|
kMockDispatch
|
|
11
11
|
} = require('./mock-symbols')
|
|
12
12
|
const { InvalidArgumentError } = require('../core/errors')
|
|
13
|
+
const { buildURL } = require('../core/util')
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Defines the scope API for an interceptor reply
|
|
@@ -70,9 +71,13 @@ class MockInterceptor {
|
|
|
70
71
|
// As per RFC 3986, clients are not supposed to send URI
|
|
71
72
|
// fragments to servers when they retrieve a document,
|
|
72
73
|
if (typeof opts.path === 'string') {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
if (opts.query) {
|
|
75
|
+
opts.path = buildURL(opts.path, opts.query)
|
|
76
|
+
} else {
|
|
77
|
+
// Matches https://github.com/nodejs/undici/blob/main/lib/fetch/index.js#L1811
|
|
78
|
+
const parsedURL = new URL(opts.path, 'data://')
|
|
79
|
+
opts.path = parsedURL.pathname + parsedURL.search
|
|
80
|
+
}
|
|
76
81
|
}
|
|
77
82
|
if (typeof opts.method === 'string') {
|
|
78
83
|
opts.method = opts.method.toUpperCase()
|
package/lib/mock/mock-utils.js
CHANGED
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
kOrigin,
|
|
9
9
|
kGetNetConnect
|
|
10
10
|
} = require('./mock-symbols')
|
|
11
|
+
const { buildURL } = require('../core/util')
|
|
11
12
|
|
|
12
13
|
function matchValue (match, value) {
|
|
13
14
|
if (typeof match === 'string') {
|
|
@@ -98,10 +99,12 @@ function getResponseData (data) {
|
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
function getMockDispatch (mockDispatches, key) {
|
|
102
|
+
const resolvedPath = key.query ? buildURL(key.path, key.query) : key.path
|
|
103
|
+
|
|
101
104
|
// Match path
|
|
102
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path }) => matchValue(path,
|
|
105
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path }) => matchValue(path, resolvedPath))
|
|
103
106
|
if (matchedMockDispatches.length === 0) {
|
|
104
|
-
throw new MockNotMatchedError(`Mock dispatch not matched for path '${
|
|
107
|
+
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`)
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
// Match method
|
|
@@ -146,12 +149,13 @@ function deleteMockDispatch (mockDispatches, key) {
|
|
|
146
149
|
}
|
|
147
150
|
|
|
148
151
|
function buildKey (opts) {
|
|
149
|
-
const { path, method, body, headers } = opts
|
|
152
|
+
const { path, method, body, headers, query } = opts
|
|
150
153
|
return {
|
|
151
154
|
path,
|
|
152
155
|
method,
|
|
153
156
|
body,
|
|
154
|
-
headers
|
|
157
|
+
headers,
|
|
158
|
+
query
|
|
155
159
|
}
|
|
156
160
|
}
|
|
157
161
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "undici",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
4
4
|
"description": "An HTTP/1.1 client, written from scratch for Node.js",
|
|
5
5
|
"homepage": "https://undici.nodejs.org",
|
|
6
6
|
"bugs": {
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"@sinonjs/fake-timers": "^9.1.2",
|
|
68
68
|
"@types/node": "^17.0.29",
|
|
69
69
|
"abort-controller": "^3.0.0",
|
|
70
|
-
"busboy": "^
|
|
70
|
+
"busboy": "^1.6.0",
|
|
71
71
|
"chai": "^4.3.4",
|
|
72
72
|
"chai-as-promised": "^7.1.1",
|
|
73
73
|
"chai-iterator": "^3.0.2",
|
|
@@ -77,8 +77,8 @@
|
|
|
77
77
|
"delay": "^5.0.0",
|
|
78
78
|
"docsify-cli": "^4.4.3",
|
|
79
79
|
"formdata-node": "^4.3.1",
|
|
80
|
-
"https-pem": "^
|
|
81
|
-
"husky": "^
|
|
80
|
+
"https-pem": "^3.0.0",
|
|
81
|
+
"husky": "^8.0.1",
|
|
82
82
|
"import-fresh": "^3.3.0",
|
|
83
83
|
"jest": "^28.0.1",
|
|
84
84
|
"jsfuzz": "^1.0.15",
|
package/types/dispatcher.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Duplex, Readable, Writable } from 'stream'
|
|
|
3
3
|
import { EventEmitter } from 'events'
|
|
4
4
|
import { IncomingHttpHeaders } from 'http'
|
|
5
5
|
import { Blob } from 'buffer'
|
|
6
|
-
import BodyReadable
|
|
6
|
+
import BodyReadable = require('./readable')
|
|
7
7
|
import { FormData } from './formdata'
|
|
8
8
|
|
|
9
9
|
type AbortSignal = unknown;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IncomingHttpHeaders } from 'http'
|
|
2
|
-
import Dispatcher
|
|
2
|
+
import Dispatcher = require('./dispatcher');
|
|
3
3
|
import { BodyInit, Headers } from './fetch'
|
|
4
4
|
|
|
5
5
|
export {
|
|
@@ -50,6 +50,8 @@ declare namespace MockInterceptor {
|
|
|
50
50
|
body?: string | RegExp | ((body: string) => boolean);
|
|
51
51
|
/** Headers to intercept on. */
|
|
52
52
|
headers?: Record<string, string | RegExp | ((body: string) => boolean)> | ((headers: Record<string, string>) => boolean);
|
|
53
|
+
/** Query params to intercept on */
|
|
54
|
+
query?: Record<string, any>;
|
|
53
55
|
}
|
|
54
56
|
export interface MockDispatch<TData extends object = object, TError extends Error = Error> extends Options {
|
|
55
57
|
times: number | null;
|