mockttp
Advanced tools
Comparing version 0.18.1 to 0.19.0
@@ -331,3 +331,4 @@ "use strict"; | ||
timingEvents, | ||
httpVersion | ||
httpVersion, | ||
${this.typeHasField('InitiatedRequest', 'tags') ? 'tags' : ''} | ||
} | ||
@@ -352,2 +353,3 @@ }` | ||
${this.typeHasField('Request', 'httpVersion') ? 'httpVersion' : ''} | ||
${this.typeHasField('Request', 'tags') ? 'tags' : ''} | ||
} | ||
@@ -366,2 +368,3 @@ }` | ||
${this.typeHasField('Response', 'timingEvents') ? 'timingEvents' : ''} | ||
${this.typeHasField('Response', 'tags') ? 'tags' : ''} | ||
} | ||
@@ -384,2 +387,3 @@ }` | ||
${this.typeHasField('Response', 'timingEvents') ? 'timingEvents' : ''} | ||
${this.typeHasField('Response', 'tags') ? 'tags' : ''} | ||
} | ||
@@ -395,2 +399,3 @@ }` | ||
remoteIpAddress | ||
${this.typeHasField('TlsRequest', 'tags') ? 'tags' : ''} | ||
} | ||
@@ -414,2 +419,4 @@ }` | ||
} | ||
if (!data.tags) | ||
data.tags = []; | ||
if (data.body) { | ||
@@ -416,0 +423,0 @@ data.body = request_utils_1.buildBodyReader(Buffer.from(data.body, 'base64'), data.headers); |
@@ -131,3 +131,3 @@ /** | ||
explain(): string; | ||
handle(clientReq: OngoingRequest, clientRes: express.Response): Promise<void>; | ||
handle(clientReq: OngoingRequest, clientRes: OngoingResponse): Promise<void>; | ||
serialize(channel: ClientServerChannel): SerializedPassThroughData; | ||
@@ -134,0 +134,0 @@ static deserialize(data: SerializedPassThroughData, channel: ClientServerChannel): PassThroughHandler; |
@@ -400,8 +400,10 @@ "use strict"; | ||
} | ||
const checkServerCertificate = !_.includes(this.ignoreHostCertificateErrors, hostname); | ||
const host = hostname + ((protocol === 'https:' && port === '443') || (protocol === 'http:' && port === '80') | ||
? '' // Omit the port if it's the default | ||
: `:${port}` // Otherwise use it | ||
); | ||
const clientCert = this.clientCertificateHostMap[host] || {}; | ||
const hostWithPort = `${hostname}:${port}`; | ||
// Ignore cert errors if the host+port or whole hostname is whitelisted | ||
const checkServerCertificate = !_.includes(this.ignoreHostCertificateErrors, hostname) && | ||
!_.includes(this.ignoreHostCertificateErrors, hostWithPort); | ||
// Use a client cert if it's listed for the host+port or whole hostname | ||
const clientCert = this.clientCertificateHostMap[hostWithPort] || | ||
this.clientCertificateHostMap[hostname] || | ||
{}; | ||
let makeRequest = protocol === 'https:' ? https.request : http.request; | ||
@@ -531,2 +533,9 @@ let family; | ||
return; | ||
// Tag responses, so programmatic examination can react to this | ||
// event, without having to parse response data or similar. | ||
const tlsAlertMatch = /SSL alert number (\d+)/.exec(e.message); | ||
if (tlsAlertMatch) { | ||
clientRes.tags.push('passthrough-tls-error:ssl-alert-' + tlsAlertMatch[1]); | ||
} | ||
clientRes.tags.push('passthrough-error:' + e.code); | ||
if (e.code === 'ECONNRESET') { | ||
@@ -533,0 +542,0 @@ // The upstream socket closed: forcibly close the downstream too, to match |
@@ -101,3 +101,4 @@ "use strict"; | ||
hostname: socket.servername, | ||
remoteIpAddress: socket.initialRemoteAddress | ||
remoteIpAddress: socket.initialRemoteAddress, | ||
tags: [] | ||
}); | ||
@@ -109,3 +110,4 @@ }); | ||
hostname: tlsSocket.servername, | ||
remoteIpAddress: tlsSocket.remoteAddress | ||
remoteIpAddress: tlsSocket.remoteAddress, | ||
tags: [] | ||
}); | ||
@@ -159,3 +161,4 @@ })); | ||
hostname: targetHost, | ||
remoteIpAddress: socket.remoteAddress | ||
remoteIpAddress: socket.remoteAddress, | ||
tags: [] | ||
}); | ||
@@ -174,3 +177,4 @@ }); | ||
hostname: targetHost, | ||
remoteIpAddress: socket.remoteAddress | ||
remoteIpAddress: socket.remoteAddress, | ||
tags: [] | ||
})); | ||
@@ -177,0 +181,0 @@ // This is a little crazy, but only a little. We create a one-off server to handle HTTP parsing, but |
@@ -172,3 +172,6 @@ "use strict"; | ||
const initiatedReq = request_utils_1.buildInitiatedRequest(request); | ||
this.eventEmitter.emit('request-initiated', Object.assign(initiatedReq, { timingEvents: _.clone(initiatedReq.timingEvents) })); | ||
this.eventEmitter.emit('request-initiated', Object.assign(initiatedReq, { | ||
timingEvents: _.clone(initiatedReq.timingEvents), | ||
tags: _.clone(initiatedReq.tags) | ||
})); | ||
}); | ||
@@ -180,3 +183,6 @@ } | ||
.then((completedReq) => { | ||
this.eventEmitter.emit('request', Object.assign(completedReq, { timingEvents: _.clone(completedReq.timingEvents) })); | ||
this.eventEmitter.emit('request', Object.assign(completedReq, { | ||
timingEvents: _.clone(completedReq.timingEvents), | ||
tags: _.clone(completedReq.tags) | ||
})); | ||
}) | ||
@@ -191,3 +197,4 @@ .catch(console.error); | ||
this.eventEmitter.emit('response', Object.assign(res, { | ||
timingEvents: _.clone(res.timingEvents) | ||
timingEvents: _.clone(res.timingEvents), | ||
tags: _.clone(res.tags) | ||
})); | ||
@@ -202,3 +209,4 @@ }) | ||
this.eventEmitter.emit('abort', Object.assign(req, { | ||
timingEvents: _.clone(req.timingEvents) | ||
timingEvents: _.clone(req.timingEvents), | ||
tags: _.clone(req.tags) | ||
})); | ||
@@ -222,7 +230,9 @@ }); | ||
const timingEvents = { startTime: Date.now(), startTimestamp: now() }; | ||
const response = request_utils_1.trackResponse(rawResponse, timingEvents); | ||
const tags = []; | ||
const response = request_utils_1.trackResponse(rawResponse, timingEvents, tags); | ||
const id = uuid(); | ||
const request = Object.assign(rawRequest, { | ||
id: id, | ||
timingEvents | ||
timingEvents, | ||
tags | ||
}); | ||
@@ -229,0 +239,0 @@ response.id = id; |
@@ -40,2 +40,3 @@ /** | ||
timingEvents: TimingEvents | {}; | ||
tags: string[]; | ||
} | ||
@@ -46,2 +47,3 @@ export interface TlsRequest { | ||
failureCause: 'closed' | 'reset' | 'cert-rejected' | 'no-shared-cipher' | 'unknown'; | ||
tags: string[]; | ||
} | ||
@@ -89,2 +91,3 @@ export interface OngoingRequest extends Request, EventEmitter { | ||
timingEvents: TimingEvents; | ||
tags: string[]; | ||
} | ||
@@ -98,2 +101,3 @@ export interface CompletedResponse { | ||
timingEvents: TimingEvents | {}; | ||
tags: string[]; | ||
} | ||
@@ -100,0 +104,0 @@ /** |
@@ -26,4 +26,4 @@ /** | ||
export declare function waitForCompletedRequest(request: OngoingRequest): Promise<CompletedRequest>; | ||
export declare function trackResponse(response: express.Response, timingEvents: TimingEvents): OngoingResponse; | ||
export declare function trackResponse(response: express.Response, timingEvents: TimingEvents, tags: string[]): OngoingResponse; | ||
export declare function waitForCompletedResponse(response: OngoingResponse): Promise<CompletedResponse>; | ||
export {}; |
@@ -193,3 +193,3 @@ "use strict"; | ||
function buildInitiatedRequest(request) { | ||
return Object.assign({}, _.pick(request, 'id', 'matchedRuleId', 'protocol', 'httpVersion', 'method', 'url', 'path', 'hostname', 'headers'), { timingEvents: request.timingEvents }); | ||
return Object.assign({}, _.pick(request, 'id', 'matchedRuleId', 'protocol', 'httpVersion', 'method', 'url', 'path', 'hostname', 'headers', 'tags'), { timingEvents: request.timingEvents }); | ||
} | ||
@@ -214,3 +214,3 @@ exports.buildInitiatedRequest = buildInitiatedRequest; | ||
exports.waitForCompletedRequest = waitForCompletedRequest; | ||
function trackResponse(response, timingEvents) { | ||
function trackResponse(response, timingEvents, tags) { | ||
let trackedResponse = response; | ||
@@ -222,2 +222,3 @@ if (!trackedResponse.getHeaders) { | ||
trackedResponse.timingEvents = timingEvents; | ||
trackedResponse.tags = tags; | ||
// Headers are sent when .writeHead or .write() are first called | ||
@@ -262,3 +263,4 @@ const trackingStream = new stream.PassThrough(); | ||
'statusMessage', | ||
'timingEvents' | ||
'timingEvents', | ||
'tags' | ||
]).assign({ | ||
@@ -265,0 +267,0 @@ headers: response.getHeaders(), |
{ | ||
"name": "mockttp", | ||
"version": "0.18.1", | ||
"version": "0.19.0", | ||
"description": "Mock HTTP server for testing HTTP clients and stubbing webservices", | ||
@@ -5,0 +5,0 @@ "main": "dist/main.js", |
@@ -358,3 +358,4 @@ /** | ||
timingEvents, | ||
httpVersion | ||
httpVersion, | ||
${this.typeHasField('InitiatedRequest', 'tags') ? 'tags' : ''} | ||
} | ||
@@ -379,2 +380,3 @@ }` | ||
${this.typeHasField('Request', 'httpVersion') ? 'httpVersion' : ''} | ||
${this.typeHasField('Request', 'tags') ? 'tags' : ''} | ||
} | ||
@@ -393,2 +395,3 @@ }` | ||
${this.typeHasField('Response', 'timingEvents') ? 'timingEvents' : ''} | ||
${this.typeHasField('Response', 'tags') ? 'tags' : ''} | ||
} | ||
@@ -411,2 +414,3 @@ }` | ||
${this.typeHasField('Response', 'timingEvents') ? 'timingEvents' : ''} | ||
${this.typeHasField('Response', 'tags') ? 'tags' : ''} | ||
} | ||
@@ -422,2 +426,3 @@ }` | ||
remoteIpAddress | ||
${this.typeHasField('TlsRequest', 'tags') ? 'tags' : ''} | ||
} | ||
@@ -443,2 +448,4 @@ }` | ||
if (!data.tags) data.tags = []; | ||
if (data.body) { | ||
@@ -445,0 +452,0 @@ data.body = buildBodyReader(Buffer.from(data.body, 'base64'), data.headers); |
@@ -528,3 +528,3 @@ /** | ||
async handle(clientReq: OngoingRequest, clientRes: express.Response) { | ||
async handle(clientReq: OngoingRequest, clientRes: OngoingResponse) { | ||
// Capture raw request data: | ||
@@ -617,10 +617,13 @@ let { method, url: reqUrl, headers } = clientReq; | ||
const checkServerCertificate = !_.includes(this.ignoreHostCertificateErrors, hostname); | ||
const host = hostname + ( | ||
(protocol === 'https:' && port === '443') || (protocol === 'http:' && port === '80') | ||
? '' // Omit the port if it's the default | ||
: `:${port}` // Otherwise use it | ||
); | ||
const clientCert = this.clientCertificateHostMap[host] || {}; | ||
const hostWithPort = `${hostname}:${port}` | ||
// Ignore cert errors if the host+port or whole hostname is whitelisted | ||
const checkServerCertificate = !_.includes(this.ignoreHostCertificateErrors, hostname) && | ||
!_.includes(this.ignoreHostCertificateErrors, hostWithPort); | ||
// Use a client cert if it's listed for the host+port or whole hostname | ||
const clientCert =this.clientCertificateHostMap[hostWithPort] || | ||
this.clientCertificateHostMap[hostname!] || | ||
{}; | ||
let makeRequest = protocol === 'https:' ? https.request : http.request; | ||
@@ -769,2 +772,10 @@ | ||
// Tag responses, so programmatic examination can react to this | ||
// event, without having to parse response data or similar. | ||
const tlsAlertMatch = /SSL alert number (\d+)/.exec(e.message); | ||
if (tlsAlertMatch) { | ||
clientRes.tags.push('passthrough-tls-error:ssl-alert-' + tlsAlertMatch[1]); | ||
} | ||
clientRes.tags.push('passthrough-error:' + e.code); | ||
if (e.code === 'ECONNRESET') { | ||
@@ -771,0 +782,0 @@ // The upstream socket closed: forcibly close the downstream too, to match |
@@ -134,3 +134,4 @@ import _ = require('lodash'); | ||
hostname: socket.servername, | ||
remoteIpAddress: socket.initialRemoteAddress! | ||
remoteIpAddress: socket.initialRemoteAddress!, | ||
tags: [] | ||
}); | ||
@@ -143,3 +144,4 @@ }); | ||
hostname: tlsSocket.servername, | ||
remoteIpAddress: tlsSocket.remoteAddress! | ||
remoteIpAddress: tlsSocket.remoteAddress!, | ||
tags: [] | ||
}); | ||
@@ -198,3 +200,4 @@ }) | ||
hostname: targetHost, | ||
remoteIpAddress: socket.remoteAddress! | ||
remoteIpAddress: socket.remoteAddress!, | ||
tags: [] | ||
}); | ||
@@ -213,3 +216,4 @@ }); | ||
hostname: targetHost, | ||
remoteIpAddress: socket.remoteAddress! | ||
remoteIpAddress: socket.remoteAddress!, | ||
tags: [] | ||
})); | ||
@@ -216,0 +220,0 @@ |
@@ -197,3 +197,6 @@ /** | ||
initiatedReq, | ||
{ timingEvents: _.clone(initiatedReq.timingEvents) } | ||
{ | ||
timingEvents: _.clone(initiatedReq.timingEvents), | ||
tags: _.clone(initiatedReq.tags) | ||
} | ||
)); | ||
@@ -209,3 +212,6 @@ }); | ||
completedReq, | ||
{ timingEvents: _.clone(completedReq.timingEvents) } | ||
{ | ||
timingEvents: _.clone(completedReq.timingEvents), | ||
tags: _.clone(completedReq.tags) | ||
} | ||
)); | ||
@@ -222,3 +228,4 @@ }) | ||
this.eventEmitter.emit('response', Object.assign(res, { | ||
timingEvents: _.clone(res.timingEvents) | ||
timingEvents: _.clone(res.timingEvents), | ||
tags: _.clone(res.tags) | ||
})); | ||
@@ -233,3 +240,4 @@ }) | ||
this.eventEmitter.emit('abort', Object.assign(req, { | ||
timingEvents: _.clone(req.timingEvents) | ||
timingEvents: _.clone(req.timingEvents), | ||
tags: _.clone(req.tags) | ||
})); | ||
@@ -249,4 +257,5 @@ } | ||
const timingEvents = { startTime: Date.now(), startTimestamp: now() }; | ||
const tags: string[] = []; | ||
const response = trackResponse(rawResponse, timingEvents); | ||
const response = trackResponse(rawResponse, timingEvents, tags); | ||
@@ -257,3 +266,4 @@ const id = uuid(); | ||
id: id, | ||
timingEvents | ||
timingEvents, | ||
tags | ||
}); | ||
@@ -260,0 +270,0 @@ response.id = id; |
@@ -58,2 +58,3 @@ /** | ||
timingEvents: TimingEvents | {}; | ||
tags: string[]; | ||
} | ||
@@ -64,3 +65,4 @@ | ||
remoteIpAddress: string; | ||
failureCause: 'closed' | 'reset' | 'cert-rejected' | 'no-shared-cipher' | 'unknown' | ||
failureCause: 'closed' | 'reset' | 'cert-rejected' | 'no-shared-cipher' | 'unknown'; | ||
tags: string[]; | ||
} | ||
@@ -118,2 +120,3 @@ | ||
timingEvents: TimingEvents; | ||
tags: string[]; | ||
} | ||
@@ -128,2 +131,3 @@ | ||
timingEvents: TimingEvents | {}; | ||
tags: string[]; | ||
} | ||
@@ -130,0 +134,0 @@ |
@@ -246,3 +246,4 @@ /** | ||
'hostname', | ||
'headers' | ||
'headers', | ||
'tags' | ||
), | ||
@@ -269,3 +270,3 @@ timingEvents: request.timingEvents | ||
export function trackResponse(response: express.Response, timingEvents: TimingEvents): OngoingResponse { | ||
export function trackResponse(response: express.Response, timingEvents: TimingEvents, tags: string[]): OngoingResponse { | ||
let trackedResponse = <OngoingResponse> response; | ||
@@ -278,2 +279,3 @@ if (!trackedResponse.getHeaders) { | ||
trackedResponse.timingEvents = timingEvents; | ||
trackedResponse.tags = tags; | ||
@@ -330,3 +332,4 @@ // Headers are sent when .writeHead or .write() are first called | ||
'statusMessage', | ||
'timingEvents' | ||
'timingEvents', | ||
'tags' | ||
]).assign({ | ||
@@ -333,0 +336,0 @@ headers: response.getHeaders(), |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
597913
10985