Comparing version 4.0.0-rc.3 to 4.0.0-rc.4
@@ -199,3 +199,3 @@ # Dispatcher | ||
* **headers** `UndiciHeaders` (optional) - Default: `null` | ||
* **idempotent** `boolean` (optional) - Default: `true` if `method` is `'HEAD'` or `'GET'` - Whether the requests can be safely retried or not. If `false` the request won't be sent until all preceeding requests in the pipeline has completed. | ||
* **idempotent** `boolean` (optional) - Default: `true` if `method` is `'HEAD'` or `'GET'` - Whether the requests can be safely retried or not. If `false` the request won't be sent until all preceding requests in the pipeline has completed. | ||
* **upgrade** `string | null` (optional) - Default: `null` - Upgrade the request. Should be used to specify the kind of upgrade i.e. `'Websocket'`. | ||
@@ -207,6 +207,6 @@ | ||
* **onError** `(error: Error) => void` - Invoked when an error has occurred. | ||
* **onUpgrade** `(statusCode: number, headers: Buffer[] | null, socket: Duplex) => void` (optional) - Invoked when request is upgraded. Required if `DispatchOptions.upgrade` is defined or `DispatchOptions.method === 'CONNECT'`. | ||
* **onHeaders** `(statusCode: number, headers: Buffer[] | null, resume: () => void) => boolean` - Invoked when statusCode and headers have been received. May be invoked multiple times due to 1xx informational headers. Not required for `upgrade` requests. | ||
* **onUpgrade** `(statusCode: number, headers: Buffer[], socket: Duplex) => void` (optional) - Invoked when request is upgraded. Required if `DispatchOptions.upgrade` is defined or `DispatchOptions.method === 'CONNECT'`. | ||
* **onHeaders** `(statusCode: number, headers: Buffer[], resume: () => void) => boolean` - Invoked when statusCode and headers have been received. May be invoked multiple times due to 1xx informational headers. Not required for `upgrade` requests. | ||
* **onData** `(chunk: Buffer) => boolean` - Invoked when response payload data is received. Not required for `upgrade` requests. | ||
* **onComplete** `(trailers: Buffer[] | null) => void` - Invoked when response payload and trailers have been received and the request has completed. Not required for `upgrade` requests. | ||
* **onComplete** `(trailers: Buffer[]) => void` - Invoked when response payload and trailers have been received and the request has completed. Not required for `upgrade` requests. | ||
@@ -213,0 +213,0 @@ #### Example 1 - Dispatch GET request |
@@ -10,13 +10,14 @@ # Errors | ||
| Error | Error Codes | Description | | ||
| ------------------------------------|---------------------------------------|---------------------------------------------------| | ||
| `InvalidArgumentError` | `UND_ERR_INVALID_ARG` | passed an invalid argument. | | ||
| `InvalidReturnValueError` | `UND_ERR_INVALID_RETURN_VALUE` | returned an invalid value. | | ||
| `RequestAbortedError` | `UND_ERR_ABORTED` | the request has been aborted by the user | | ||
| `ClientDestroyedError` | `UND_ERR_DESTROYED` | trying to use a destroyed client. | | ||
| `ClientClosedError` | `UND_ERR_CLOSED` | trying to use a closed client. | | ||
| `SocketError` | `UND_ERR_SOCKET` | there is an error with the socket. | | ||
| `NotSupportedError` | `UND_ERR_NOT_SUPPORTED` | encountered unsupported functionality. | | ||
| `RequestContentLengthMismatchError` | `UND_ERR_REQ_CONTENT_LENGTH_MISMATCH`| request body does not match content-length header | | ||
| `InformationalError` | `UND_ERR_INFO` | expected error with reason | | ||
| `TrailerMismatchError` | `UND_ERR_TRAILER_MISMATCH` | trailers did not match specification | | ||
| Error | Error Codes | Description | | ||
| ------------------------------------|---------------------------------------|----------------------------------------------------| | ||
| `InvalidArgumentError` | `UND_ERR_INVALID_ARG` | passed an invalid argument. | | ||
| `InvalidReturnValueError` | `UND_ERR_INVALID_RETURN_VALUE` | returned an invalid value. | | ||
| `RequestAbortedError` | `UND_ERR_ABORTED` | the request has been aborted by the user | | ||
| `ClientDestroyedError` | `UND_ERR_DESTROYED` | trying to use a destroyed client. | | ||
| `ClientClosedError` | `UND_ERR_CLOSED` | trying to use a closed client. | | ||
| `SocketError` | `UND_ERR_SOCKET` | there is an error with the socket. | | ||
| `NotSupportedError` | `UND_ERR_NOT_SUPPORTED` | encountered unsupported functionality. | | ||
| `RequestContentLengthMismatchError` | `UND_ERR_REQ_CONTENT_LENGTH_MISMATCH`| request body does not match content-length header | | ||
| `RequestContentLengthMismatchError` | `UND_ERR_RES_CONTENT_LENGTH_MISMATCH`| response body does not match content-length header | | ||
| `InformationalError` | `UND_ERR_INFO` | expected error with reason | | ||
| `TrailerMismatchError` | `UND_ERR_TRAILER_MISMATCH` | trailers did not match specification | |
@@ -60,2 +60,3 @@ # Class: MockPool | ||
* **body** `string | RegExp | (body: string) => boolean` - (optional) - a matcher for the HTTP request body. | ||
* **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. | ||
@@ -143,3 +144,3 @@ ### Return: `MockInterceptor` | ||
#### Example - Mocked request with query body, headers and trailers | ||
#### Example - Mocked request with query body, request headers and response headers and trailers | ||
@@ -157,3 +158,7 @@ ```js | ||
method: 'POST', | ||
body: 'form1=data1&form2=data2' | ||
body: 'form1=data1&form2=data2', | ||
headers: { | ||
'User-Agent': 'undici', | ||
Host: 'example.com' | ||
} | ||
}).reply(200, { foo: 'bar' }, { | ||
@@ -171,3 +176,8 @@ headers: { 'content-type': 'application/json' }, | ||
method: 'POST', | ||
body: 'form1=data1&form2=data2' | ||
body: 'form1=data1&form2=data2', | ||
headers: { | ||
foo: 'bar', | ||
'User-Agent': 'undici', | ||
Host: 'example.com' | ||
} | ||
}) | ||
@@ -198,4 +208,8 @@ | ||
path: '/foo', | ||
method: new RegExp('^GET$'), | ||
method: /^GET$/, | ||
body: (value) => value === 'form=data', | ||
headers: { | ||
'User-Agent': 'undici', | ||
Host: /^example.com$/ | ||
} | ||
}).reply(200, 'foo') | ||
@@ -205,3 +219,8 @@ | ||
method: 'GET', | ||
body: 'form=data' | ||
body: 'form=data', | ||
headers: { | ||
foo: 'bar', | ||
'User-Agent': 'undici', | ||
Host: 'example.com' | ||
} | ||
}) | ||
@@ -208,0 +227,0 @@ // Will match and return mocked data |
@@ -10,5 +10,6 @@ import Dispatcher from './types/dispatcher' | ||
import MockAgent from './types/mock-agent' | ||
import mockErrors from './types/mock-errors' | ||
import { request, pipeline, stream, connect, upgrade } from './types/api' | ||
export { Dispatcher, Pool, Client, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, MockClient, MockPool, MockAgent } | ||
export { Dispatcher, Pool, Client, errors, Agent, request, stream, pipeline, connect, upgrade, setGlobalDispatcher, getGlobalDispatcher, MockClient, MockPool, MockAgent, mockErrors } | ||
export default Undici | ||
@@ -34,2 +35,3 @@ | ||
var MockAgent: typeof import('./types/mock-agent'); | ||
var mockErrors: typeof import('./types/mock-errors'); | ||
} |
@@ -14,2 +14,3 @@ 'use strict' | ||
const MockPool = require('./lib/mock/mock-pool') | ||
const mockErrors = require('./lib/mock/mock-errors') | ||
@@ -94,1 +95,2 @@ Object.assign(Dispatcher.prototype, api) | ||
module.exports.MockAgent = MockAgent | ||
module.exports.mockErrors = mockErrors |
@@ -14,2 +14,6 @@ 'use strict' | ||
if (typeof callback !== 'function') { | ||
throw new InvalidArgumentError('invalid callback') | ||
} | ||
const { signal, opaque } = opts | ||
@@ -65,5 +69,5 @@ | ||
this.callback = null | ||
process.nextTick((self, callback, err, opaque) => { | ||
self.runInAsyncScope(callback, null, err, { opaque }) | ||
}, this, callback, err, opaque) | ||
queueMicrotask(() => { | ||
this.runInAsyncScope(callback, null, err, { opaque }) | ||
}) | ||
} | ||
@@ -82,6 +86,2 @@ } | ||
if (typeof callback !== 'function') { | ||
throw new InvalidArgumentError('invalid callback') | ||
} | ||
try { | ||
@@ -91,3 +91,7 @@ const connectHandler = new ConnectHandler(opts, callback) | ||
} catch (err) { | ||
process.nextTick(callback, err, { opaque: opts && opts.opaque }) | ||
if (typeof callback !== 'function') { | ||
throw err | ||
} | ||
const opaque = opts && opts.opaque | ||
queueMicrotask(() => callback(err, { opaque })) | ||
} | ||
@@ -94,0 +98,0 @@ } |
@@ -133,6 +133,7 @@ 'use strict' | ||
if (callback) { | ||
// TODO: Does this need queueMicrotask? | ||
this.callback = null | ||
process.nextTick((self, callback, err, opaque) => { | ||
self.runInAsyncScope(callback, null, err, { opaque }) | ||
}, this, callback, err, opaque) | ||
queueMicrotask(() => { | ||
this.runInAsyncScope(callback, null, err, { opaque }) | ||
}) | ||
} | ||
@@ -167,7 +168,7 @@ | ||
} catch (err) { | ||
if (typeof callback === 'function') { | ||
process.nextTick(callback, err, { opaque: opts && opts.opaque }) | ||
} else { | ||
if (typeof callback !== 'function') { | ||
throw err | ||
} | ||
const opaque = opts && opts.opaque | ||
queueMicrotask(() => callback(err, { opaque })) | ||
} | ||
@@ -174,0 +175,0 @@ } |
@@ -152,5 +152,5 @@ 'use strict' | ||
this.callback = null | ||
process.nextTick((self, callback, err, opaque) => { | ||
self.runInAsyncScope(callback, null, err, { opaque }) | ||
}, this, callback, err, opaque) | ||
queueMicrotask(() => { | ||
this.runInAsyncScope(callback, null, err, { opaque }) | ||
}) | ||
} | ||
@@ -177,7 +177,7 @@ | ||
} catch (err) { | ||
if (typeof callback === 'function') { | ||
process.nextTick(callback, err, { opaque: opts && opts.opaque }) | ||
} else { | ||
if (typeof callback !== 'function') { | ||
throw err | ||
} | ||
const opaque = opts && opts.opaque | ||
queueMicrotask(() => callback(err, { opaque })) | ||
} | ||
@@ -184,0 +184,0 @@ } |
@@ -15,2 +15,6 @@ 'use strict' | ||
if (typeof callback !== 'function') { | ||
throw new InvalidArgumentError('invalid callback') | ||
} | ||
const { signal, opaque } = opts | ||
@@ -68,5 +72,5 @@ | ||
this.callback = null | ||
process.nextTick((self, callback, err, opaque) => { | ||
self.runInAsyncScope(callback, null, err, { opaque }) | ||
}, this, callback, err, opaque) | ||
queueMicrotask(() => { | ||
this.runInAsyncScope(callback, null, err, { opaque }) | ||
}) | ||
} | ||
@@ -85,6 +89,2 @@ } | ||
if (typeof callback !== 'function') { | ||
throw new InvalidArgumentError('invalid callback') | ||
} | ||
try { | ||
@@ -98,3 +98,7 @@ const upgradeHandler = new UpgradeHandler(opts, callback) | ||
} catch (err) { | ||
process.nextTick(callback, err, { opaque: opts && opts.opaque }) | ||
if (typeof callback !== 'function') { | ||
throw err | ||
} | ||
const opaque = opts && opts.opaque | ||
queueMicrotask(() => callback(err, { opaque })) | ||
} | ||
@@ -101,0 +105,0 @@ } |
@@ -12,2 +12,3 @@ 'use strict' | ||
RequestContentLengthMismatchError, | ||
ResponseContentLengthMismatchError, | ||
TrailerMismatchError, | ||
@@ -285,3 +286,3 @@ InvalidArgumentError, | ||
if (this[kDestroyed]) { | ||
process.nextTick(callback, new ClientDestroyedError(), null) | ||
queueMicrotask(() => callback(new ClientDestroyedError(), null)) | ||
return | ||
@@ -321,3 +322,3 @@ } | ||
} else { | ||
process.nextTick(callback, null, null) | ||
queueMicrotask(() => callback(null, null)) | ||
} | ||
@@ -351,3 +352,3 @@ return | ||
if (!this[kSocket]) { | ||
process.nextTick(onDestroyed) | ||
queueMicrotask(onDestroyed) | ||
} else { | ||
@@ -454,2 +455,8 @@ util.destroy(this[kSocket].on('close', onDestroyed), err) | ||
this.resume = this.resume.bind(this) | ||
this.bytesRead = 0 | ||
this.trailer = '' | ||
this.keepAlive = '' | ||
this.contentLength = '' | ||
} | ||
@@ -581,6 +588,7 @@ | ||
onHeaderValue (buf) { | ||
const len = this.headers.length | ||
let len = this.headers.length | ||
if ((len & 1) === 1) { | ||
this.headers.push(buf) | ||
len += 1 | ||
} else { | ||
@@ -590,2 +598,11 @@ this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) | ||
const key = this.headers[len - 2] | ||
if (key.length === 10 && key.toString().toLowerCase() === 'keep-alive') { | ||
this.keepAlive += buf.toString() | ||
} else if (key.length === 7 && key.toString().toLowerCase() === 'trailer') { | ||
this.trailer += buf.toString() | ||
} else if (key.length === 14 && key.toString().toLowerCase() === 'content-length') { | ||
this.contentLength += buf.toString() | ||
} | ||
this.trackHeader(buf.length) | ||
@@ -659,3 +676,3 @@ } | ||
onHeadersComplete (statusCode, upgrade, shouldKeepAlive) { | ||
const { client, socket, headers: rawHeaders } = this | ||
const { client, socket, headers } = this | ||
@@ -721,23 +738,4 @@ /* istanbul ignore next: difficult to make a test case for */ | ||
let keepAlive | ||
let trailers | ||
let looking = true | ||
for (let n = 0; n < rawHeaders.length && looking; n += 2) { | ||
const key = rawHeaders[n] | ||
const val = rawHeaders[n + 1] | ||
if (!keepAlive && key.length === 10 && key.toString().toLowerCase() === 'keep-alive') { | ||
keepAlive = val | ||
looking = !trailers | ||
} else if (!trailers && key.length === 7 && key.toString().toLowerCase() === 'trailer') { | ||
trailers = val | ||
looking = !keepAlive | ||
} | ||
} | ||
this.trailers = trailers ? trailers.toString().toLowerCase().split(/,\s*/) : [] | ||
if (shouldKeepAlive && client[kPipelining]) { | ||
const keepAliveTimeout = keepAlive ? util.parseKeepAliveTimeout(keepAlive) : null | ||
const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null | ||
@@ -763,3 +761,3 @@ if (keepAliveTimeout != null) { | ||
try { | ||
if (request.onHeaders(statusCode, rawHeaders, this.resume) === false) { | ||
if (request.onHeaders(statusCode, headers, this.resume) === false) { | ||
return constants.ERROR.PAUSED | ||
@@ -801,2 +799,4 @@ } | ||
this.bytesRead += buf.length | ||
try { | ||
@@ -812,3 +812,3 @@ if (request.onData(buf) === false) { | ||
onMessageComplete () { | ||
const { client, socket, statusCode, upgrade, trailers, headers: rawTrailers, shouldKeepAlive } = this | ||
const { client, socket, statusCode, upgrade, trailer, headers, contentLength, bytesRead, shouldKeepAlive } = this | ||
@@ -829,3 +829,6 @@ if (socket.destroyed && (!statusCode || shouldKeepAlive)) { | ||
this.statusCode = null | ||
this.trailers = null | ||
this.bytesRead = 0 | ||
this.contentLength = '' | ||
this.trailer = '' | ||
this.keepAlive = '' | ||
@@ -840,7 +843,8 @@ assert(this.headers.length % 2 === 0) | ||
const trailers = trailer ? trailer.split(/,\s*/) : [] | ||
for (let i = 0; i < trailers.length; i++) { | ||
const trailer = trailers[i] | ||
let found = false | ||
for (let n = 0; n < rawTrailers.length; n += 2) { | ||
const key = rawTrailers[n] | ||
for (let n = 0; n < headers.length; n += 2) { | ||
const key = headers[n] | ||
if (key.length === trailer.length && key.toString().toLowerCase() === trailer.toLowerCase()) { | ||
@@ -857,4 +861,10 @@ found = true | ||
/* istanbul ignore next: should be handled by llhttp? */ | ||
if (request.method !== 'HEAD' && contentLength && bytesRead !== parseInt(contentLength, 10)) { | ||
util.destroy(socket, new ResponseContentLengthMismatchError()) | ||
return -1 | ||
} | ||
try { | ||
request.onComplete(rawTrailers.length ? rawTrailers : null) | ||
request.onComplete(headers) | ||
} catch (err) { | ||
@@ -1175,3 +1185,3 @@ request.onError(err) | ||
if (client[kRunning] > 0 && (request.upgrade || request.method === 'CONNECT')) { | ||
// Don't dispatch an upgrade until all preceeding requests have completed. | ||
// Don't dispatch an upgrade until all preceding requests have completed. | ||
// A misbehaving server might upgrade the connection before all pipelined | ||
@@ -1178,0 +1188,0 @@ // request has completed. |
@@ -97,6 +97,16 @@ 'use strict' | ||
this.message = message || 'Request body length does not match content-length header' | ||
this.code = 'UND_ERR_CONTENT_LENGTH_MISMATCH' | ||
this.code = 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH' | ||
} | ||
} | ||
class ResponseContentLengthMismatchError extends UndiciError { | ||
constructor (message) { | ||
super(message) | ||
Error.captureStackTrace(this, ResponseContentLengthMismatchError) | ||
this.name = 'ResponseContentLengthMismatchError' | ||
this.message = message || 'Response body length does not match content-length header' | ||
this.code = 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH' | ||
} | ||
} | ||
class TrailerMismatchError extends UndiciError { | ||
@@ -167,3 +177,4 @@ constructor (message) { | ||
SocketError, | ||
NotSupportedError | ||
NotSupportedError, | ||
ResponseContentLengthMismatchError | ||
} |
@@ -192,3 +192,3 @@ 'use strict' | ||
) { | ||
request.contentLength = parseInt(val) | ||
request.contentLength = parseInt(val, 10) | ||
if (!Number.isFinite(request.contentLength)) { | ||
@@ -195,0 +195,0 @@ throw new InvalidArgumentError('invalid content-length header') |
@@ -150,3 +150,3 @@ 'use strict' | ||
const m = val.toString().match(KEEPALIVE_TIMEOUT_EXPR) | ||
return m ? parseInt(m[1]) * 1000 : null | ||
return m ? parseInt(m[1], 10) * 1000 : null | ||
} | ||
@@ -153,0 +153,0 @@ |
'use strict' | ||
const { MockNotMatchedError } = require('./mock-errors') | ||
const { | ||
@@ -25,11 +26,25 @@ kDispatches, | ||
function buildMatcher ({ path, method, body }) { | ||
return (mockDispatch) => { | ||
const pathMatch = matchValue(mockDispatch.path, path) | ||
const methodMatch = matchValue(mockDispatch.method, method) | ||
const bodyMatch = typeof mockDispatch.body !== 'undefined' ? matchValue(mockDispatch.body, body) : true | ||
return pathMatch && methodMatch && bodyMatch | ||
function matchHeaders (mockDispatch, headers) { | ||
if (typeof mockDispatch.headers === 'undefined') { | ||
return true | ||
} | ||
if (typeof headers !== 'object' || typeof mockDispatch.headers !== 'object') { | ||
return false | ||
} | ||
for (const [matchHeaderName, matchHeaderValue] of Object.entries(mockDispatch.headers)) { | ||
if (!matchValue(matchHeaderValue, headers[matchHeaderName])) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
function matchKey (mockDispatch, { path, method, body, headers }) { | ||
const pathMatch = matchValue(mockDispatch.path, path) | ||
const methodMatch = matchValue(mockDispatch.method, method) | ||
const bodyMatch = typeof mockDispatch.body !== 'undefined' ? matchValue(mockDispatch.body, body) : true | ||
const headersMatch = matchHeaders(mockDispatch, headers) | ||
return pathMatch && methodMatch && bodyMatch && headersMatch | ||
} | ||
function getResponseData (data) { | ||
@@ -40,9 +55,27 @@ return typeof data === 'object' ? JSON.stringify(data) : data.toString() | ||
function getMockDispatch (mockDispatches, key) { | ||
const matcher = buildMatcher(key) | ||
return mockDispatches.find(dispatch => { | ||
if (dispatch.consumed) { | ||
return false | ||
} | ||
return matcher(dispatch) | ||
}) | ||
// Match path | ||
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path }) => matchValue(path, key.path)) | ||
if (matchedMockDispatches.length === 0) { | ||
throw new MockNotMatchedError(`Mock dispatch not matched for path '${key.path}'`) | ||
} | ||
// Match method | ||
matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key.method)) | ||
if (matchedMockDispatches.length === 0) { | ||
throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}'`) | ||
} | ||
// Match body | ||
matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== 'undefined' ? matchValue(body, key.body) : true) | ||
if (matchedMockDispatches.length === 0) { | ||
throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}'`) | ||
} | ||
// Match headers | ||
matchedMockDispatches = matchedMockDispatches.filter((mockDispatch) => matchHeaders(mockDispatch, key.headers)) | ||
if (matchedMockDispatches.length === 0) { | ||
throw new MockNotMatchedError(`Mock dispatch not matched for headers '${typeof key.headers === 'object' ? JSON.stringify(key.headers) : key.headers}'`) | ||
} | ||
return matchedMockDispatches[0] | ||
} | ||
@@ -62,3 +95,3 @@ | ||
} | ||
return buildMatcher(key) | ||
return matchKey(dispatch, key) | ||
}) | ||
@@ -71,7 +104,8 @@ if (index !== -1) { | ||
function buildKey (opts) { | ||
const { path, method, body } = opts | ||
const { path, method, body, headers } = opts | ||
return { | ||
path: path, | ||
method: method, | ||
body: body | ||
path, | ||
method, | ||
body, | ||
headers | ||
} | ||
@@ -100,6 +134,2 @@ } | ||
if (!mockDispatch) { | ||
return false | ||
} | ||
// Parse mockDispatch data | ||
@@ -159,10 +189,17 @@ const { data: { statusCode, data, headers, trailers, error }, delay, persist } = mockDispatch | ||
if (agent[kIsMockActive]) { | ||
let foundMockDispatch = false | ||
foundMockDispatch = mockDispatch.call(this, opts, handler) | ||
if (!foundMockDispatch) { | ||
const netConnect = agent[kGetNetConnect]() | ||
if (checkNetConnect(netConnect, origin)) { | ||
originalDispatch.call(this, opts, handler) | ||
try { | ||
mockDispatch.call(this, opts, handler) | ||
} catch (error) { | ||
if (error instanceof MockNotMatchedError) { | ||
const netConnect = agent[kGetNetConnect]() | ||
if (netConnect === false) { | ||
throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)`) | ||
} | ||
if (checkNetConnect(netConnect, origin)) { | ||
originalDispatch.call(this, opts, handler) | ||
} else { | ||
throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)`) | ||
} | ||
} else { | ||
throw new Error(`Unable to find mock dispatch and real dispatches are disabled for ${origin}`) | ||
throw error | ||
} | ||
@@ -169,0 +206,0 @@ } |
{ | ||
"name": "undici", | ||
"version": "4.0.0-rc.3", | ||
"version": "4.0.0-rc.4", | ||
"description": "An HTTP/1.1 client, written from scratch for Node.js", | ||
@@ -42,3 +42,2 @@ "homepage": "https://undici.nodejs.org", | ||
"bench": "concurrently -k -s first npm:bench:server npm:bench:run", | ||
"bench:simd": "concurrently -k -s first npm:bench:server npm:bench:run:simd", | ||
"bench:server": "node benchmarks/server.js", | ||
@@ -52,13 +51,13 @@ "prebench:run": "node benchmarks/wait.js", | ||
"@sinonjs/fake-timers": "^7.0.5", | ||
"@types/node": "^14.14.39", | ||
"@types/node": "^15.0.2", | ||
"abort-controller": "^3.0.0", | ||
"concurrently": "^6.0.2", | ||
"concurrently": "^6.1.0", | ||
"cronometro": "^0.8.0", | ||
"docsify-cli": "^4.4.2", | ||
"docsify-cli": "^4.4.3", | ||
"https-pem": "^2.0.0", | ||
"husky": "^6.0.0", | ||
"jest": "^26.4.0", | ||
"jest": "^26.6.3", | ||
"pre-commit": "^1.2.2", | ||
"proxy": "^1.0.2", | ||
"proxyquire": "^2.0.1", | ||
"proxyquire": "^2.1.3", | ||
"semver": "^7.3.5", | ||
@@ -68,3 +67,3 @@ "sinon": "^10.0.0", | ||
"standard": "^16.0.3", | ||
"tap": "^15.0.0", | ||
"tap": "^15.0.9", | ||
"tsd": "^0.14.0", | ||
@@ -71,0 +70,0 @@ "wait-on": "^5.3.0" |
@@ -20,5 +20,5 @@ # undici | ||
The benchmark is a simple `hello world` [example](benchmarks/index.js) using a | ||
The benchmark is a simple `hello world` [example](benchmarks/benchmark.js) using a | ||
number of unix sockets (connections) with a pipelining depth of 10 running on Node 16. | ||
The benchmarks have the [simd](https://github.com/WebAssembly/simd) feature enabled. | ||
The benchmarks below have the [simd](https://github.com/WebAssembly/simd) feature enabled. | ||
@@ -186,3 +186,3 @@ ### Connections 1 | ||
Uncidi will only use pipelining if configured with a `pipelining` factor | ||
Undici will only use pipelining if configured with a `pipelining` factor | ||
greater than `1`. | ||
@@ -189,0 +189,0 @@ |
@@ -51,3 +51,3 @@ export = Errors | ||
name: 'RequestContentLengthMismatchError'; | ||
code: 'UND_ERR_CONTENT_LENGTH_MISMATCH'; | ||
code: 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH'; | ||
} | ||
@@ -54,0 +54,0 @@ |
import Agent from './agent' | ||
import MockPool from './mock-pool' | ||
import MockClient from './mock-client' | ||
import Dispatcher from './dispatcher' | ||
@@ -5,0 +3,0 @@ |
@@ -43,2 +43,4 @@ import { IncomingHttpHeaders } from 'http' | ||
body?: string | RegExp | ((body: string) => boolean); | ||
/** Headers to intercept on. */ | ||
headers?: Record<string, string | RegExp | ((body: string) => boolean)>; | ||
} | ||
@@ -45,0 +47,0 @@ export interface MockDispatch<TData extends object = object, TError extends Error = Error> extends Options { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
417173
63
4820