Comparing version 14.0.0-beta.17 to 14.0.0-beta.18
@@ -9,8 +9,7 @@ 'use strict' | ||
const { restoreOverriddenClientRequest } = require('./intercept') | ||
const { BatchInterceptor } = require('@mswjs/interceptors') | ||
const { EventEmitter } = require('stream') | ||
const { gzipSync, brotliCompressSync, deflateSync } = require('zlib') | ||
const { | ||
default: nodeInterceptors, | ||
} = require('@mswjs/interceptors/presets/node') | ||
const { EventEmitter } = require('stream') | ||
const SEPARATOR = '\n<<<<<<-- cut here -->>>>>>\n' | ||
@@ -20,7 +19,5 @@ let recordingInProgress = false | ||
// TODO: Consider use one BatchInterceptor (and not one for intercept and one for record) | ||
const interceptor = new BatchInterceptor({ | ||
name: 'nock-interceptor', | ||
interceptors: nodeInterceptors, | ||
}) | ||
// TODO: don't reuse the nodeInterceptors, create new ones. | ||
const clientRequestInterceptor = nodeInterceptors[0] | ||
const fetchRequestInterceptor = nodeInterceptors[2] | ||
@@ -231,105 +228,133 @@ function getScope(options) { | ||
// 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) | ||
clientRequestInterceptor.apply() | ||
fetchRequestInterceptor.apply() | ||
clientRequestInterceptor.on('request', async function ({ request }) { | ||
await recordRequest(request) | ||
}) | ||
fetchRequestInterceptor.on('request', async function ({ request }) { | ||
await recordRequest(request) | ||
}) | ||
// 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 | ||
async function recordRequest(mswRequest) { | ||
const request = mswRequest.clone() | ||
const { options } = common.normalizeClientRequestArgs(request.url) | ||
options.method = request.method | ||
const proto = options.protocol.slice(0, -1) | ||
const req = new EventEmitter() | ||
req.on('response', function () { | ||
debug(thisRecordingId, 'intercepting', proto, 'request to record') | ||
// 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 | ||
// Intercept "res.once('end', ...)"-like event | ||
interceptor.once( | ||
'response', | ||
async function ({ response: mswResponse }) { | ||
const response = mswResponse.clone() | ||
debug(thisRecordingId, proto, 'intercepted request ended') | ||
const req = new EventEmitter() | ||
req.on('response', function () { | ||
debug(thisRecordingId, 'intercepting', proto, 'request to record') | ||
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') | ||
} | ||
clientRequestInterceptor.once('response', async function ({ response }) { | ||
await recordResponse(response) | ||
}) | ||
fetchRequestInterceptor.once('response', async function ({ response }) { | ||
// fetch decompresses the body automatically, so we need to recompress it | ||
const codings = | ||
response.headers | ||
.get('content-encoding') | ||
?.toLowerCase() | ||
.split(',') | ||
.map(c => c.trim()) || [] | ||
const headers = Object.fromEntries(response.headers.entries()) | ||
const res = { | ||
statusCode: response.status, | ||
headers, | ||
rawHeaders: headers, | ||
} | ||
let body = await response.arrayBuffer() | ||
for (const coding of codings) { | ||
if (coding === 'gzip') { | ||
body = gzipSync(body) | ||
} else if (coding === 'deflate') { | ||
body = deflateSync(body) | ||
} else if (coding === 'br') { | ||
body = brotliCompressSync(body) | ||
} | ||
} | ||
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, | ||
}) | ||
await recordResponse(new Response(body, response)) | ||
}) | ||
debug('out:', out) | ||
// Intercept "res.once('end', ...)"-like event | ||
async function recordResponse(mswResponse) { | ||
const response = mswResponse.clone() | ||
debug(thisRecordingId, proto, 'intercepted request ended') | ||
// 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 | ||
} | ||
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') | ||
} | ||
outputs.push(out) | ||
const headers = Object.fromEntries(response.headers.entries()) | ||
const res = { | ||
statusCode: response.status, | ||
headers, | ||
rawHeaders: headers, | ||
} | ||
if (!dontPrint) { | ||
if (useSeparator) { | ||
if (typeof out !== 'string') { | ||
out = JSON.stringify(out, null, 2) | ||
} | ||
logging(SEPARATOR + out + SEPARATOR) | ||
} else { | ||
logging(out) | ||
} | ||
} | ||
}, | ||
) | ||
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('finished setting up intercepting') | ||
debug('out:', out) | ||
// 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' | ||
// 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 | ||
} | ||
}) | ||
// 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') | ||
}, | ||
) | ||
outputs.push(out) | ||
if (!dontPrint) { | ||
if (useSeparator) { | ||
if (typeof out !== 'string') { | ||
out = JSON.stringify(out, null, 2) | ||
} | ||
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' | ||
} | ||
}) | ||
// 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') | ||
} | ||
} | ||
@@ -344,3 +369,4 @@ | ||
interceptor.dispose() | ||
clientRequestInterceptor.dispose() | ||
fetchRequestInterceptor.dispose() | ||
restoreOverriddenClientRequest() | ||
@@ -347,0 +373,0 @@ recordingInProgress = false |
@@ -10,3 +10,3 @@ { | ||
], | ||
"version": "14.0.0-beta.17", | ||
"version": "14.0.0-beta.18", | ||
"author": "Pedro Teixeira <pedro.teixeira@gmail.com>", | ||
@@ -13,0 +13,0 @@ "repository": { |
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
186562
3598