Comparing version 14.0.0-beta.8 to 14.0.0-beta.9
@@ -579,6 +579,6 @@ 'use strict' | ||
/** | ||
* @param {Request} request | ||
* @param {Request} request | ||
*/ | ||
function convertFetchRequestToClientRequest(request) { | ||
const url = new URL(request.url); | ||
const url = new URL(request.url) | ||
const options = { | ||
@@ -591,5 +591,5 @@ ...urlToOptions(url), | ||
proto: url.protocol.slice(0, -1), | ||
headers: Object.fromEntries(request.headers.entries()) | ||
}; | ||
headers: Object.fromEntries(request.headers.entries()), | ||
} | ||
// By default, Node adds a host header, but for maximum backward compatibility, we are now removing it. | ||
@@ -602,3 +602,3 @@ // However, we need to consider leaving the header and fixing the tests. | ||
return new http.ClientRequest(options); | ||
return new http.ClientRequest(options) | ||
} | ||
@@ -605,0 +605,0 @@ |
@@ -18,19 +18,19 @@ 'use strict' | ||
/** | ||
* @param {import('http').IncomingMessage} message | ||
* @param {import('http').IncomingMessage} message | ||
*/ | ||
function createResponse(message) { | ||
const responseBodyOrNull = responseStatusCodesWithoutBody.includes( | ||
message.statusCode || 200 | ||
message.statusCode || 200, | ||
) | ||
? null | ||
: new ReadableStream({ | ||
start(controller) { | ||
message.on('data', (chunk) => controller.enqueue(chunk)) | ||
message.on('end', () => controller.close()) | ||
message.on('error', (error) => controller.error(error)) | ||
}, | ||
cancel() { | ||
message.destroy() | ||
}, | ||
}) | ||
start(controller) { | ||
message.on('data', chunk => controller.enqueue(chunk)) | ||
message.on('end', () => controller.close()) | ||
message.on('error', error => controller.error(error)) | ||
}, | ||
cancel() { | ||
message.destroy() | ||
}, | ||
}) | ||
@@ -37,0 +37,0 @@ const rawHeaders = new Headers() |
@@ -15,3 +15,5 @@ 'use strict' | ||
const { FetchInterceptor } = require('@mswjs/interceptors/fetch') | ||
const { default: nodeInterceptors } = require('@mswjs/interceptors/presets/node') | ||
const { | ||
default: nodeInterceptors, | ||
} = require('@mswjs/interceptors/presets/node') | ||
const { createResponse } = require('./create_response') | ||
@@ -198,3 +200,4 @@ const { once } = require('events') | ||
debug( | ||
`matched base path (${interceptors.length} interceptor${interceptors.length > 1 ? 's' : '' | ||
`matched base path (${interceptors.length} interceptor${ | ||
interceptors.length > 1 ? 's' : '' | ||
})`, | ||
@@ -337,3 +340,3 @@ ) | ||
} else { | ||
isNockActive = false; | ||
isNockActive = false | ||
interceptor.dispose() | ||
@@ -377,3 +380,3 @@ http.ClientRequest = originalClientRequest | ||
overrideClientRequest() | ||
interceptor.apply(); | ||
interceptor.apply() | ||
// Force msw to forward Nock's error instead of coerce it into 500 error | ||
@@ -383,49 +386,54 @@ interceptor.on('unhandledException', ({ controller, error }) => { | ||
}) | ||
interceptor.on('request', async function ({ request: mswRequest, controller }) { | ||
const request = mswRequest.clone() | ||
const { options } = common.normalizeClientRequestArgs(request.url) | ||
options.proto = options.protocol.slice(0, -1) | ||
options.method = request.method | ||
const interceptors = interceptorsFor(options) | ||
if (isOn() && interceptors) { | ||
const matches = interceptors.some(interceptor => | ||
interceptor.matchOrigin(options) | ||
) | ||
const allowUnmocked = interceptors.some( | ||
interceptor => interceptor.options.allowUnmocked | ||
) | ||
interceptor.on( | ||
'request', | ||
async function ({ request: mswRequest, controller }) { | ||
const request = mswRequest.clone() | ||
const { options } = common.normalizeClientRequestArgs(request.url) | ||
options.proto = options.protocol.slice(0, -1) | ||
options.method = request.method | ||
const interceptors = interceptorsFor(options) | ||
if (isOn() && interceptors) { | ||
const matches = interceptors.some(interceptor => | ||
interceptor.matchOrigin(options), | ||
) | ||
const allowUnmocked = interceptors.some( | ||
interceptor => interceptor.options.allowUnmocked, | ||
) | ||
const nockRequest = common.convertFetchRequestToClientRequest(request); | ||
if (!matches && allowUnmocked) { | ||
globalEmitter.emit('no match', nockRequest) | ||
} else { | ||
nockRequest.on('response', nockResponse => { | ||
// TODO: Consider put empty headers object as default when create the ClientRequest | ||
if (nockResponse.req.headers) { | ||
// forward Nock request headers to the MSW request | ||
Object.entries(nockResponse.req.headers).map(([k, v]) => mswRequest.headers.set(k, v)) | ||
} | ||
const nockRequest = common.convertFetchRequestToClientRequest(request) | ||
if (!matches && allowUnmocked) { | ||
globalEmitter.emit('no match', nockRequest) | ||
} else { | ||
nockRequest.on('response', nockResponse => { | ||
// TODO: Consider put empty headers object as default when create the ClientRequest | ||
if (nockResponse.req.headers) { | ||
// forward Nock request headers to the MSW request | ||
Object.entries(nockResponse.req.headers).map(([k, v]) => | ||
mswRequest.headers.set(k, v), | ||
) | ||
} | ||
const response = createResponse(nockResponse) | ||
controller.respondWith(response) | ||
}) | ||
const response = createResponse(nockResponse) | ||
controller.respondWith(response) | ||
}) | ||
const promise = Promise.race([ | ||
// TODO: temp hacky way to handle allowUnmocked in startPlayback | ||
once(nockRequest, 'real-request'), | ||
once(nockRequest, 'error'), | ||
once(nockRequest, 'response'), | ||
]) | ||
const buffer = await request.arrayBuffer() | ||
nockRequest.write(buffer) | ||
nockRequest.end() | ||
await promise | ||
const promise = Promise.race([ | ||
// TODO: temp hacky way to handle allowUnmocked in startPlayback | ||
once(nockRequest, 'real-request'), | ||
once(nockRequest, 'error'), | ||
once(nockRequest, 'response'), | ||
]) | ||
const buffer = await request.arrayBuffer() | ||
nockRequest.write(buffer) | ||
nockRequest.end() | ||
await promise | ||
} | ||
} else { | ||
globalEmitter.emit('no match', options) | ||
if (!(isOff() || isEnabledForNetConnect(options))) { | ||
throw new NetConnectNotAllowedError(options.host, options.path) | ||
} | ||
} | ||
} else { | ||
globalEmitter.emit('no match', options) | ||
if (!(isOff() || isEnabledForNetConnect(options))) { | ||
throw new NetConnectNotAllowedError(options.host, options.path) | ||
} | ||
} | ||
}) | ||
}, | ||
) | ||
isNockActive = true | ||
@@ -432,0 +440,0 @@ } |
'use strict' | ||
const { request_overrider: debug } = require('./debug') | ||
const { | ||
IncomingMessage, | ||
ClientRequest, | ||
} = require('http') | ||
const { IncomingMessage, ClientRequest } = require('http') | ||
const propagate = require('propagate') | ||
@@ -9,0 +6,0 @@ const common = require('./common') |
@@ -11,3 +11,5 @@ 'use strict' | ||
const { FetchInterceptor } = require('@mswjs/interceptors/fetch') | ||
const { default: nodeInterceptors } = require('@mswjs/interceptors/presets/node') | ||
const { | ||
default: nodeInterceptors, | ||
} = require('@mswjs/interceptors/presets/node') | ||
const { EventEmitter } = require('stream') | ||
@@ -229,99 +231,105 @@ | ||
// We override the requests so that we can save information on them before executing. | ||
interceptor.apply(); | ||
interceptor.on('request', async function ({ request: mswRequest, requestId }) { | ||
const request = mswRequest.clone() | ||
const { options } = common.normalizeClientRequestArgs(request.url) | ||
options.method = request.method | ||
const proto = options.protocol.slice(0, -1) | ||
interceptor.apply() | ||
interceptor.on( | ||
'request', | ||
async function ({ request: mswRequest, requestId }) { | ||
const request = mswRequest.clone() | ||
const { options } = common.normalizeClientRequestArgs(request.url) | ||
options.method = request.method | ||
const proto = options.protocol.slice(0, -1) | ||
// Node 0.11 https.request calls http.request -- don't want to record things | ||
// twice. | ||
/* istanbul ignore if */ | ||
if (options._recording) { | ||
return | ||
} | ||
options._recording = true | ||
// Node 0.11 https.request calls http.request -- don't want to record things | ||
// twice. | ||
/* istanbul ignore if */ | ||
if (options._recording) { | ||
return | ||
} | ||
options._recording = true | ||
const req = new EventEmitter(); | ||
req.on('response', function () { | ||
debug(thisRecordingId, 'intercepting', proto, 'request to record') | ||
const req = new EventEmitter() | ||
req.on('response', function () { | ||
debug(thisRecordingId, 'intercepting', proto, 'request to record') | ||
// Intercept "res.once('end', ...)"-like event | ||
interceptor.once('response', async function ({ response: mswResponse }) { | ||
const response = mswResponse.clone() | ||
debug(thisRecordingId, proto, 'intercepted request ended') | ||
// Intercept "res.once('end', ...)"-like event | ||
interceptor.once( | ||
'response', | ||
async function ({ response: mswResponse }) { | ||
const response = mswResponse.clone() | ||
debug(thisRecordingId, proto, 'intercepted request ended') | ||
let reqheaders | ||
// Ignore request headers completely unless it was explicitly enabled by the user (see README) | ||
if (enableReqHeadersRecording) { | ||
// We never record user-agent headers as they are worse than useless - | ||
// they actually make testing more difficult without providing any benefit (see README) | ||
reqheaders = Object.fromEntries(request.headers.entries()) | ||
common.deleteHeadersField(reqheaders, 'user-agent') | ||
} | ||
let reqheaders | ||
// Ignore request headers completely unless it was explicitly enabled by the user (see README) | ||
if (enableReqHeadersRecording) { | ||
// We never record user-agent headers as they are worse than useless - | ||
// they actually make testing more difficult without providing any benefit (see README) | ||
reqheaders = Object.fromEntries(request.headers.entries()) | ||
common.deleteHeadersField(reqheaders, 'user-agent') | ||
} | ||
const headers = Object.fromEntries(response.headers.entries()) | ||
const res = { | ||
statusCode: response.status, | ||
headers, | ||
rawHeaders: headers, | ||
} | ||
const headers = Object.fromEntries(response.headers.entries()) | ||
const res = { | ||
statusCode: response.status, | ||
headers, | ||
rawHeaders: headers, | ||
} | ||
const generateFn = outputObjects | ||
? generateRequestAndResponseObject | ||
: generateRequestAndResponse | ||
let out = generateFn({ | ||
req: options, | ||
bodyChunks: [Buffer.from(await request.arrayBuffer())], | ||
options, | ||
res, | ||
dataChunks: [Buffer.from(await response.arrayBuffer())], | ||
reqheaders, | ||
}) | ||
const generateFn = outputObjects | ||
? generateRequestAndResponseObject | ||
: generateRequestAndResponse | ||
let out = generateFn({ | ||
req: options, | ||
bodyChunks: [Buffer.from(await request.arrayBuffer())], | ||
options, | ||
res, | ||
dataChunks: [Buffer.from(await response.arrayBuffer())], | ||
reqheaders, | ||
}) | ||
debug('out:', out) | ||
debug('out:', out) | ||
// Check that the request was made during the current recording. | ||
// If it hasn't then skip it. There is no other simple way to handle | ||
// this as it depends on the timing of requests and responses. Throwing | ||
// will make some recordings/unit tests fail randomly depending on how | ||
// fast/slow the response arrived. | ||
// If you are seeing this error then you need to make sure that all | ||
// the requests made during a single recording session finish before | ||
// ending the same recording session. | ||
if (thisRecordingId !== currentRecordingId) { | ||
debug('skipping recording of an out-of-order request', out) | ||
return | ||
} | ||
// Check that the request was made during the current recording. | ||
// If it hasn't then skip it. There is no other simple way to handle | ||
// this as it depends on the timing of requests and responses. Throwing | ||
// will make some recordings/unit tests fail randomly depending on how | ||
// fast/slow the response arrived. | ||
// If you are seeing this error then you need to make sure that all | ||
// the requests made during a single recording session finish before | ||
// ending the same recording session. | ||
if (thisRecordingId !== currentRecordingId) { | ||
debug('skipping recording of an out-of-order request', out) | ||
return | ||
} | ||
outputs.push(out) | ||
outputs.push(out) | ||
if (!dontPrint) { | ||
if (useSeparator) { | ||
if (typeof out !== 'string') { | ||
out = JSON.stringify(out, null, 2) | ||
if (!dontPrint) { | ||
if (useSeparator) { | ||
if (typeof out !== 'string') { | ||
out = JSON.stringify(out, null, 2) | ||
} | ||
logging(SEPARATOR + out + SEPARATOR) | ||
} else { | ||
logging(out) | ||
} | ||
} | ||
logging(SEPARATOR + out + SEPARATOR) | ||
} else { | ||
logging(out) | ||
} | ||
}, | ||
) | ||
debug('finished setting up intercepting') | ||
// We override both the http and the https modules; when we are | ||
// serializing the request, we need to know which was called. | ||
// By stuffing the state, we can make sure that nock records | ||
// the intended protocol. | ||
if (proto === 'https') { | ||
options.proto = 'https' | ||
} | ||
}) | ||
debug('finished setting up intercepting') | ||
// We override both the http and the https modules; when we are | ||
// serializing the request, we need to know which was called. | ||
// By stuffing the state, we can make sure that nock records | ||
// the intended protocol. | ||
if (proto === 'https') { | ||
options.proto = 'https' | ||
} | ||
}) | ||
// This is a massive change, we are trying to change minimum code, so we emit end event here | ||
// because mswjs take care for these events | ||
// TODO: refactor the recorder, we no longer need all the listeners and can just record the request we get from MSW | ||
req.emit('response') | ||
}) | ||
// This is a massive change, we are trying to change minimum code, so we emit end event here | ||
// because mswjs take care for these events | ||
// TODO: refactor the recorder, we no longer need all the listeners and can just record the request we get from MSW | ||
req.emit('response') | ||
}, | ||
) | ||
} | ||
@@ -328,0 +336,0 @@ |
@@ -10,3 +10,3 @@ { | ||
], | ||
"version": "14.0.0-beta.8", | ||
"version": "14.0.0-beta.9", | ||
"author": "Pedro Teixeira <pedro.teixeira@gmail.com>", | ||
@@ -26,3 +26,3 @@ "repository": { | ||
"dependencies": { | ||
"@mswjs/interceptors": "^0.33.1", | ||
"@mswjs/interceptors": "^0.33.2", | ||
"json-stringify-safe": "^5.0.1", | ||
@@ -29,0 +29,0 @@ "propagate": "^2.0.0" |
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
186087
3579
Updated@mswjs/interceptors@^0.33.2