unexpected-mitm
Advanced tools
Comparing version 9.0.3 to 9.1.0
@@ -1,2 +0,2 @@ | ||
/* global setImmediate, after, console */ | ||
/* global setImmediate, process, after, console */ | ||
var messy = require('messy'), | ||
@@ -17,2 +17,6 @@ createMitm = require('mitm'), | ||
function checkEnvFlag(varName) { | ||
return process.env[varName] === 'true'; | ||
} | ||
function isRegExp(obj) { | ||
@@ -22,2 +26,6 @@ return Object.prototype.toString.call(obj) === '[object RegExp]'; | ||
function isTextualBody(message, content) { | ||
return message.hasTextualContentType && bufferCanBeInterpretedAsUtf8(content); | ||
} | ||
function formatHeaderObj(headerObj) { | ||
@@ -58,2 +66,9 @@ var result = {}; | ||
function trimHeaders(message) { | ||
delete message.headers['Content-Length']; | ||
delete message.headers['Transfer-Encoding']; | ||
delete message.headers.Connection; | ||
delete message.headers.Date; | ||
} | ||
function trimMessage(message) { | ||
@@ -63,3 +78,3 @@ if (typeof message.body !== 'undefined') { | ||
delete message.body; | ||
} else if (new messy.Message({headers: {'Content-Type': message.headers['Content-Type']}}).hasTextualContentType && bufferCanBeInterpretedAsUtf8(message.body)) { | ||
} else if (isTextualBody(new messy.Message({headers: {'Content-Type': message.headers['Content-Type']}}), message.body)) { | ||
message.body = message.body.toString('utf-8'); | ||
@@ -80,6 +95,3 @@ } | ||
if (message.headers) { | ||
delete message.headers['Content-Length']; | ||
delete message.headers['Transfer-Encoding']; | ||
delete message.headers.Connection; | ||
delete message.headers.Date; | ||
trimHeaders(message); | ||
if (Object.keys(message.headers).length === 0) { | ||
@@ -104,2 +116,18 @@ delete message.headers; | ||
function trimMockResponse(mockResponse) { | ||
var responseProperties = {}; | ||
responseProperties.statusCode = mockResponse.statusCode; | ||
responseProperties.statusMessage = mockResponse.statusMessage; | ||
responseProperties.protocolName = mockResponse.protocolName; | ||
responseProperties.protocolVersion = mockResponse.protocolVersion; | ||
responseProperties.headers = formatHeaderObj(mockResponse.headers.valuesByName); | ||
if (mockResponse.body) { | ||
// read out the messy decoded body | ||
responseProperties.body = mockResponse.body; | ||
} | ||
return responseProperties; | ||
} | ||
function trimRecordedExchange(recordedExchange) { | ||
@@ -299,3 +327,32 @@ return { | ||
function responseForVerification(response, validationBlock) { | ||
// arrange to use formatted headers | ||
response.headers = formatHeaderObj(response.headers); | ||
// remove superfluous headers from the response | ||
trimHeaders(response); | ||
// call messy for decoding of text values | ||
var messyMessage = new messy.Message({headers: {'Content-Type': response.headers['Content-Type']}, unchunkedBody: response.body}); | ||
if (response.body.length === 0) { | ||
// remove an empty body from the comparison | ||
delete response.body; | ||
} else if (messyMessage.hasTextualContentType) { | ||
// read a messy decoded version of the body | ||
response.body = messyMessage.body; | ||
} | ||
if (validationBlock) { | ||
if (validationBlock.ignoreHeaders) { | ||
validationBlock.ignoreHeaders.forEach(function (headerKey) { | ||
delete response.headers[messy.formatHeaderName(headerKey)]; | ||
}); | ||
} | ||
} | ||
return response; | ||
} | ||
module.exports = { | ||
@@ -495,2 +552,55 @@ name: 'unexpected-mitm', | ||
function createVerifier(expect, verifyBlocks) { | ||
return function (fulfilmentValue, httpConversation, httpConversationSatisfySpec) { | ||
var httpExchanges = httpConversation.exchanges.slice(0); | ||
var httpVerificationSatisfySpec = { | ||
exchanges: [] | ||
}; | ||
function nextItem() { | ||
var exchange = httpExchanges.shift(); | ||
var verifyOptions = verifyBlocks.shift(); | ||
var request; | ||
if (exchange) { | ||
request = exchange.request; | ||
return performRequest({ | ||
encrypted: request.encrypted, | ||
headers: request.headers.toJSON(), | ||
method: request.method, | ||
host: request.host, | ||
port: request.port, | ||
path: request.url, | ||
body: request.body | ||
}).then(function (responseResult) { | ||
httpVerificationSatisfySpec.exchanges.push({ | ||
request: {}, | ||
response: responseForVerification(responseResult, verifyOptions.response) | ||
}); | ||
return nextItem(); | ||
}); | ||
} else { | ||
return httpVerificationSatisfySpec; | ||
} | ||
} | ||
return expect.promise(function (resolve, reject) { | ||
resolve(nextItem()); | ||
}).then(function (httpVerificationSatisfySpec) { | ||
expect.withError(function () { | ||
return expect(httpConversation, 'to satisfy', httpVerificationSatisfySpec); | ||
}, function (e) { | ||
expect.errorMode = 'bubble'; | ||
expect.fail({ | ||
diff: function (output) { | ||
return output.text('The mock and service have diverged.\n\n').append(e.getErrorMessage(output)); | ||
} | ||
}); | ||
}); | ||
}); | ||
}; | ||
} | ||
function executeMitm(expect, subject) { | ||
@@ -617,18 +727,26 @@ var mitm = createMitm(), | ||
}) | ||
.addAssertion('<any> with http mocked out [with extra info] <array|object> <assertion>', function (expect, subject, requestDescriptions) { // ... | ||
.addAssertion('<any> with http mocked out [and verified] [with extra info] <array|object> <assertion>', function (expect, subject, requestDescriptions) { // ... | ||
expect.errorMode = 'nested'; | ||
var mitm = createMitm(); | ||
var shouldBeVerified = checkEnvFlag('UNEXPECTED_MITM_VERIFY') || expect.flags['and verified']; | ||
var shouldReturnExtraInfo = expect.flags['with extra info']; | ||
return expect.promise(function (resolve, reject) { | ||
if (!Array.isArray(requestDescriptions)) { | ||
if (typeof requestDescriptions === 'undefined') { | ||
requestDescriptions = []; | ||
} else { | ||
requestDescriptions = [requestDescriptions]; | ||
} | ||
if (!Array.isArray(requestDescriptions)) { | ||
if (typeof requestDescriptions === 'undefined') { | ||
requestDescriptions = []; | ||
} else { | ||
// duplicate descriptions to allow array consumption | ||
requestDescriptions = requestDescriptions.slice(0); | ||
requestDescriptions = [requestDescriptions]; | ||
} | ||
} else { | ||
// duplicate descriptions to allow array consumption | ||
requestDescriptions = requestDescriptions.slice(0); | ||
} | ||
var verifyBlocks = requestDescriptions.map(function (description) { | ||
var verifyBlock = description.verify || {}; | ||
delete description.verify; | ||
return verifyBlock; | ||
}); | ||
var assertionPromise = expect.promise(function (resolve, reject) { | ||
var httpConversation = new messy.HttpConversation(), | ||
@@ -745,4 +863,5 @@ httpConversationSatisfySpec = {exchanges: []}, | ||
* assertion is reject()ed, we have already | ||
* resolve()d which is effectively ignored | ||
* thus we proceed with our output. | ||
* resolve()d thus the rejection of the former | ||
* is effectively ignored and we proceed with | ||
* our output. | ||
*/ | ||
@@ -832,3 +951,3 @@ | ||
request: expectedRequestProperties, | ||
response: mockResponseError || mockResponse | ||
response: mockResponseError || trimMockResponse(mockResponse) | ||
}); | ||
@@ -849,3 +968,3 @@ | ||
return expect(httpConversation, 'to satisfy', httpConversationSatisfySpec).then(function () { | ||
if (expect.flags['with extra info']) { | ||
if (shouldBeVerified || shouldReturnExtraInfo) { | ||
return [fulfilmentValue, httpConversation, httpConversationSatisfySpec]; | ||
@@ -859,4 +978,22 @@ } else { | ||
}); | ||
if (shouldBeVerified) { | ||
expect.errorMode = 'default'; | ||
var verifier = createVerifier(expect, verifyBlocks); | ||
return assertionPromise.spread(function (fulfilmentValue, httpConversation, httpConversationSatisfySpec) { | ||
return verifier(fulfilmentValue, httpConversation, httpConversationSatisfySpec).then(function () { | ||
if (shouldReturnExtraInfo) { | ||
return [fulfilmentValue, httpConversation, httpConversationSatisfySpec]; | ||
} else { | ||
return fulfilmentValue; | ||
} | ||
}); | ||
}); | ||
} | ||
return assertionPromise; | ||
}); | ||
} | ||
}; |
{ | ||
"name": "unexpected-mitm", | ||
"version": "9.0.3", | ||
"version": "9.1.0", | ||
"description": "Unexpected plugin for the mitm library", | ||
@@ -5,0 +5,0 @@ "author": "Andreas Lind <andreas@one.com>", |
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
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
49649
883
2
2