Socket
Socket
Sign inDemoInstall

mockttp

Package Overview
Dependencies
Maintainers
1
Versions
125
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mockttp - npm Package Compare versions

Comparing version 1.0.4 to 1.0.5

12

custom-typings/node-type-extensions.d.ts

@@ -31,5 +31,8 @@ // There's a few places where we attach extra data to some node objects during

__timingInfo?: {
initialSocket?: number; // Initial raw socket time
tunnelSetup?: number; // Latest CONNECT completion, if any
tlsConnected?: number; // Latest TLS handshake completion, if any
initialSocket: number; // Initial raw socket time, since unix epoch
// High-precision timestamps:
initialSocketTimestamp: number;
tunnelSetupTimestamp?: number; // Latest CONNECT completion, if any
tlsConnectedTimestamp?: number; // Latest TLS handshake completion, if any
};

@@ -53,5 +56,6 @@

// We cache the initially set remote address on sockets, because it's cleared
// We cache the initially set remote address & port on sockets, because it's cleared
// before the TLS error callback is called, exactly when we want to read it.
initialRemoteAddress?: string;
initialRemotePort?: number;

@@ -58,0 +62,0 @@ // Marker used to detect whether client errors should be reported as TLS issues

@@ -59,2 +59,3 @@ /**

private typeHasField;
private optionalField;
private typeHasInputField;

@@ -61,0 +62,0 @@ enableDebug(): void;

@@ -136,3 +136,3 @@ "use strict";

id,
${this.typeHasField('MockedEndpoint', 'explanation') ? 'explanation' : ''}
${this.optionalField('MockedEndpoint', 'explanation')}
}

@@ -157,3 +157,3 @@ }`, {

id,
${this.typeHasField('MockedEndpoint', 'explanation') ? 'explanation' : ''}
${this.optionalField('MockedEndpoint', 'explanation')}
}

@@ -177,6 +177,6 @@ }`, {

body,
${this.typeHasField('Request', 'timingEvents') ? 'timingEvents' : ''}
${this.typeHasField('Request', 'httpVersion') ? 'httpVersion' : ''}
${this.optionalField('Request', 'timingEvents')}
${this.optionalField('Request', 'httpVersion')}
}
${this.typeHasField('MockedEndpoint', 'isPending') ? 'isPending' : ''}
${this.optionalField('MockedEndpoint', 'isPending')}
}

@@ -326,2 +326,7 @@ }`, {

}
optionalField(typeName, fieldName) {
return (this.typeHasField(typeName, fieldName))
? fieldName
: '';
}
typeHasInputField(typeName, fieldName) {

@@ -351,3 +356,3 @@ const type = _.find(this.mockServerSchema.types, { name: typeName });

id,
${this.typeHasField('MockedEndpoint', 'explanation') ? 'explanation' : ''}
${this.optionalField('MockedEndpoint', 'explanation')}
}

@@ -410,3 +415,3 @@ }`);

httpVersion,
${this.typeHasField('InitiatedRequest', 'tags') ? 'tags' : ''}
${this.optionalField('InitiatedRequest', 'tags')}
}

@@ -420,3 +425,3 @@ }`

id,
${this.typeHasField('Request', 'matchedRuleId') ? 'matchedRuleId' : ''}
${this.optionalField('Request', 'matchedRuleId')}
protocol,

@@ -430,5 +435,5 @@ method,

body,
${this.typeHasField('Request', 'timingEvents') ? 'timingEvents' : ''}
${this.typeHasField('Request', 'httpVersion') ? 'httpVersion' : ''}
${this.typeHasField('Request', 'tags') ? 'tags' : ''}
${this.optionalField('Request', 'timingEvents')}
${this.optionalField('Request', 'httpVersion')}
${this.optionalField('Request', 'tags')}
}

@@ -446,4 +451,4 @@ }`

body,
${this.typeHasField('Response', 'timingEvents') ? 'timingEvents' : ''}
${this.typeHasField('Response', 'tags') ? 'tags' : ''}
${this.optionalField('Response', 'timingEvents')}
${this.optionalField('Response', 'tags')}
}

@@ -465,4 +470,4 @@ }`

body,
${this.typeHasField('Response', 'timingEvents') ? 'timingEvents' : ''}
${this.typeHasField('Response', 'tags') ? 'tags' : ''}
${this.optionalField('Response', 'timingEvents')}
${this.optionalField('Response', 'tags')}
}

@@ -478,3 +483,5 @@ }`

remoteIpAddress
${this.typeHasField('TlsRequest', 'tags') ? 'tags' : ''}
${this.optionalField('TlsRequest', 'remotePort')}
${this.optionalField('TlsRequest', 'tags')}
${this.optionalField('TlsRequest', 'timingEvents')}
}

@@ -481,0 +488,0 @@ }`

@@ -16,2 +16,3 @@ "use strict";

const httpolyglot = require("@httptoolkit/httpolyglot");
const now = require("performance-now");
const destroyable_server_1 = require("../util/destroyable-server");

@@ -32,3 +33,3 @@ const tls_1 = require("../util/tls");

_handle.oncertcb = function (info) {
var _a, _b, _c, _d, _e;
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
tlsSocket.servername = info.servername;

@@ -38,3 +39,4 @@ tlsSocket.initialRemoteAddress = tlsSocket.remoteAddress || // Normal case

((_d = (_c = (_b = tlsSocket._handle) === null || _b === void 0 ? void 0 : _b._parentWrap) === null || _c === void 0 ? void 0 : _c.stream) === null || _d === void 0 ? void 0 : _d.remoteAddress); // For HTTP/2 CONNECT
return (_e = loadSNI) === null || _e === void 0 ? void 0 : _e.apply(this, arguments);
tlsSocket.initialRemotePort = tlsSocket.remotePort || ((_e = tlsSocket._parent) === null || _e === void 0 ? void 0 : _e.remotePort) || ((_h = (_g = (_f = tlsSocket._handle) === null || _f === void 0 ? void 0 : _f._parentWrap) === null || _g === void 0 ? void 0 : _g.stream) === null || _h === void 0 ? void 0 : _h.remotePort);
return (_j = loadSNI) === null || _j === void 0 ? void 0 : _j.apply(this, arguments);
};

@@ -54,7 +56,9 @@ };

// than the initial TLS handshake for an unhappy disconnection.
const timing = socket.__timingInfo || {};
const tlsSetupDuration = timing.tlsConnected - (timing.tunnelSetup || timing.initialSocket);
const maxTlsRejectionTime = (!Object.is(tlsSetupDuration, NaN) && tlsSetupDuration !== 0)
? tlsSetupDuration * 10
: 5000;
const timing = socket.__timingInfo;
const tlsSetupDuration = timing
? timing.tlsConnectedTimestamp - (timing.tunnelSetupTimestamp || timing.initialSocketTimestamp)
: 0;
const maxTlsRejectionTime = !Object.is(tlsSetupDuration, NaN)
? Math.max(tlsSetupDuration * 10, 100) // Ensure a sensible minimum
: 2000;
util_1.delay(maxTlsRejectionTime).then(resolve);

@@ -88,3 +92,3 @@ })

? 'reset'
: 'unknown'; // Something else.
: 'unknown'; // Something \else.
if (cause === 'unknown')

@@ -94,2 +98,28 @@ console.log('Unknown TLS error:', error);

}
function buildTimingInfo() {
return { initialSocket: Date.now(), initialSocketTimestamp: now() };
}
function buildTlsError(socket, cause) {
var _a, _b, _c;
const timingInfo = socket.__timingInfo || ((_a = socket._parent) === null || _a === void 0 ? void 0 : _a.__timingInfo) ||
buildTimingInfo();
return {
failureCause: cause,
hostname: socket.servername,
// These only work because of oncertcb monkeypatch above
remoteIpAddress: socket.remoteAddress || // Normal case
((_b = socket._parent) === null || _b === void 0 ? void 0 : _b.remoteAddress) || // Pre-certCB error, e.g. timeout
socket.initialRemoteAddress,
remotePort: socket.remotePort || ((_c = socket._parent) === null || _c === void 0 ? void 0 : _c.remotePort) ||
socket.initialRemotePort,
tags: [],
timingEvents: {
startTime: timingInfo.initialSocket,
connectTimestamp: timingInfo.initialSocketTimestamp,
tunnelTimestamp: timingInfo.tunnelSetupTimestamp,
handshakeTimestamp: timingInfo.tlsConnectedTimestamp,
failureTimestamp: now()
}
};
}
// The low-level server that handles all the sockets & TLS. The server will correctly call the

@@ -136,3 +166,3 @@ // given handler for both HTTP & HTTPS direct connections, or connections when used as an

server.on('connection', (socket) => {
socket.__timingInfo = socket.__timingInfo || { initialSocket: Date.now() };
socket.__timingInfo = socket.__timingInfo || buildTimingInfo();
// All sockets are initially marked as using unencrypted upstream connections.

@@ -151,13 +181,8 @@ // If TLS is used, this is upgraded to 'true' by secureConnection below.

else if (!socket.__timingInfo) {
socket.__timingInfo = { initialSocket: Date.now() };
socket.__timingInfo = buildTimingInfo();
}
socket.__timingInfo.tlsConnected = Date.now();
socket.__timingInfo.tlsConnectedTimestamp = now();
socket.lastHopEncrypted = true;
ifTlsDropped(socket, () => {
tlsClientErrorListener(socket, {
failureCause: 'closed',
hostname: socket.servername,
remoteIpAddress: socket.remoteAddress || socket.initialRemoteAddress,
tags: []
});
tlsClientErrorListener(socket, buildTlsError(socket, 'closed'));
});

@@ -173,12 +198,3 @@ });

server.on('tlsClientError', (error, socket) => {
var _a;
// These only work because of oncertcb monkeypatch above
tlsClientErrorListener(socket, {
failureCause: getCauseFromError(error),
hostname: socket.servername,
remoteIpAddress: socket.remoteAddress || // Normal case
((_a = socket._parent) === null || _a === void 0 ? void 0 : _a.remoteAddress) || // Pre-certCB error, e.g. timeout
socket.initialRemoteAddress,
tags: []
});
tlsClientErrorListener(socket, buildTlsError(socket, getCauseFromError(error)));
});

@@ -207,3 +223,3 @@ // If the server receives a HTTP/HTTPS CONNECT request, Pretend to tunnel, then just re-handle:

socket.write('HTTP/' + req.httpVersion + ' 200 OK\r\n\r\n', 'utf-8', () => {
socket.__timingInfo.tunnelSetup = Date.now();
socket.__timingInfo.tunnelSetupTimestamp = now();
server.emit('connection', socket);

@@ -210,0 +226,0 @@ });

@@ -46,5 +46,14 @@ /**

remoteIpAddress: string;
remotePort: number;
failureCause: 'closed' | 'reset' | 'cert-rejected' | 'no-shared-cipher' | 'unknown';
tags: string[];
timingEvents: TlsTimingEvents;
}
export interface TlsTimingEvents {
startTime: number;
connectTimestamp: number;
failureTimestamp: number;
handshakeTimestamp?: number;
tunnelTimestamp?: number;
}
export interface OngoingRequest extends Request, EventEmitter {

@@ -51,0 +60,0 @@ body: ParsedBody;

{
"name": "mockttp",
"version": "1.0.4",
"version": "1.0.5",
"description": "Mock HTTP server for testing HTTP clients and stubbing webservices",

@@ -5,0 +5,0 @@ "main": "dist/main.js",

@@ -287,2 +287,8 @@ /**

private optionalField(typeName: string, fieldName: string): string {
return (this.typeHasField(typeName, fieldName))
? fieldName
: '';
}
private typeHasInputField(typeName: string, fieldName: string): boolean {

@@ -351,3 +357,3 @@ const type: any = _.find(this.mockServerSchema.types, { name: typeName });

id,
${this.typeHasField('MockedEndpoint', 'explanation') ? 'explanation' : ''}
${this.optionalField('MockedEndpoint', 'explanation')}
}

@@ -377,3 +383,3 @@ }`, {

id,
${this.typeHasField('MockedEndpoint', 'explanation') ? 'explanation' : ''}
${this.optionalField('MockedEndpoint', 'explanation')}
}

@@ -420,3 +426,3 @@ }`

id,
${this.typeHasField('MockedEndpoint', 'explanation') ? 'explanation' : ''}
${this.optionalField('MockedEndpoint', 'explanation')}
}

@@ -480,3 +486,3 @@ }`, {

httpVersion,
${this.typeHasField('InitiatedRequest', 'tags') ? 'tags' : ''}
${this.optionalField('InitiatedRequest', 'tags')}
}

@@ -490,3 +496,3 @@ }`

id,
${this.typeHasField('Request', 'matchedRuleId') ? 'matchedRuleId' : ''}
${this.optionalField('Request', 'matchedRuleId')}
protocol,

@@ -500,5 +506,5 @@ method,

body,
${this.typeHasField('Request', 'timingEvents') ? 'timingEvents' : ''}
${this.typeHasField('Request', 'httpVersion') ? 'httpVersion' : ''}
${this.typeHasField('Request', 'tags') ? 'tags' : ''}
${this.optionalField('Request', 'timingEvents')}
${this.optionalField('Request', 'httpVersion')}
${this.optionalField('Request', 'tags')}
}

@@ -516,4 +522,4 @@ }`

body,
${this.typeHasField('Response', 'timingEvents') ? 'timingEvents' : ''}
${this.typeHasField('Response', 'tags') ? 'tags' : ''}
${this.optionalField('Response', 'timingEvents')}
${this.optionalField('Response', 'tags')}
}

@@ -535,4 +541,4 @@ }`

body,
${this.typeHasField('Response', 'timingEvents') ? 'timingEvents' : ''}
${this.typeHasField('Response', 'tags') ? 'tags' : ''}
${this.optionalField('Response', 'timingEvents')}
${this.optionalField('Response', 'tags')}
}

@@ -548,3 +554,5 @@ }`

remoteIpAddress
${this.typeHasField('TlsRequest', 'tags') ? 'tags' : ''}
${this.optionalField('TlsRequest', 'remotePort')}
${this.optionalField('TlsRequest', 'tags')}
${this.optionalField('TlsRequest', 'timingEvents')}
}

@@ -642,6 +650,6 @@ }`

body,
${this.typeHasField('Request', 'timingEvents') ? 'timingEvents' : ''}
${this.typeHasField('Request', 'httpVersion') ? 'httpVersion' : ''}
${this.optionalField('Request', 'timingEvents')}
${this.optionalField('Request', 'httpVersion')}
}
${this.typeHasField('MockedEndpoint', 'isPending') ? 'isPending' : ''}
${this.optionalField('MockedEndpoint', 'isPending')}
}

@@ -648,0 +656,0 @@ }`, {

@@ -7,4 +7,4 @@ import _ = require('lodash');

import * as streams from 'stream';
import SocketWrapper = require('_stream_wrap');
import httpolyglot = require('@httptoolkit/httpolyglot');
import now = require("performance-now");

@@ -33,2 +33,5 @@ import { TlsRequest } from '../types';

tlsSocket._handle?._parentWrap?.stream?.remoteAddress; // For HTTP/2 CONNECT
tlsSocket.initialRemotePort = tlsSocket.remotePort ||
tlsSocket._parent?.remotePort ||
tlsSocket._handle?._parentWrap?.stream?.remotePort;

@@ -59,7 +62,10 @@ return loadSNI?.apply(this, arguments as any);

// than the initial TLS handshake for an unhappy disconnection.
const timing = socket.__timingInfo || {};
const tlsSetupDuration = timing.tlsConnected! - (timing.tunnelSetup! || timing.initialSocket!);
const maxTlsRejectionTime = (!Object.is(tlsSetupDuration, NaN) && tlsSetupDuration !== 0)
? tlsSetupDuration * 10
: 5000;
const timing = socket.__timingInfo;
const tlsSetupDuration = timing
? timing.tlsConnectedTimestamp! - (timing.tunnelSetupTimestamp! || timing.initialSocketTimestamp)
: 0;
const maxTlsRejectionTime = !Object.is(tlsSetupDuration, NaN)
? Math.max(tlsSetupDuration * 10, 100) // Ensure a sensible minimum
: 2000;
delay(maxTlsRejectionTime).then(resolve);

@@ -94,3 +100,3 @@ })

? 'reset'
: 'unknown'; // Something else.
: 'unknown'; // Something \else.

@@ -102,2 +108,35 @@ if (cause === 'unknown') console.log('Unknown TLS error:', error);

function buildTimingInfo(): Required<net.Socket>['__timingInfo'] {
return { initialSocket: Date.now(), initialSocketTimestamp: now() };
}
function buildTlsError(
socket: tls.TLSSocket,
cause: TlsRequest['failureCause']
): TlsRequest {
const timingInfo = socket.__timingInfo ||
socket._parent?.__timingInfo ||
buildTimingInfo();
return {
failureCause: cause,
hostname: socket.servername,
// These only work because of oncertcb monkeypatch above
remoteIpAddress: socket.remoteAddress || // Normal case
socket._parent?.remoteAddress || // Pre-certCB error, e.g. timeout
socket.initialRemoteAddress!, // Recorded by certCB monkeypatch
remotePort: socket.remotePort ||
socket._parent?.remotePort ||
socket.initialRemotePort!,
tags: [],
timingEvents: {
startTime: timingInfo.initialSocket,
connectTimestamp: timingInfo.initialSocketTimestamp,
tunnelTimestamp: timingInfo.tunnelSetupTimestamp,
handshakeTimestamp: timingInfo.tlsConnectedTimestamp,
failureTimestamp: now()
}
};
}
// The low-level server that handles all the sockets & TLS. The server will correctly call the

@@ -147,3 +186,3 @@ // given handler for both HTTP & HTTPS direct connections, or connections when used as an

server.on('connection', (socket: net.Socket) => {
socket.__timingInfo = socket.__timingInfo || { initialSocket: Date.now() };
socket.__timingInfo = socket.__timingInfo || buildTimingInfo();

@@ -163,15 +202,10 @@ // All sockets are initially marked as using unencrypted upstream connections.

} else if (!socket.__timingInfo) {
socket.__timingInfo = { initialSocket: Date.now() };
socket.__timingInfo = buildTimingInfo();
}
socket.__timingInfo!.tlsConnected = Date.now();
socket.__timingInfo!.tlsConnectedTimestamp = now();
socket.lastHopEncrypted = true;
ifTlsDropped(socket, () => {
tlsClientErrorListener(socket, {
failureCause: 'closed',
hostname: socket.servername,
remoteIpAddress: socket.remoteAddress || socket.initialRemoteAddress!,
tags: []
});
tlsClientErrorListener(socket, buildTlsError(socket, 'closed'));
});

@@ -189,11 +223,3 @@ });

server.on('tlsClientError', (error: Error, socket: tls.TLSSocket) => {
// These only work because of oncertcb monkeypatch above
tlsClientErrorListener(socket, {
failureCause: getCauseFromError(error),
hostname: socket.servername,
remoteIpAddress: socket.remoteAddress || // Normal case
socket._parent?.remoteAddress || // Pre-certCB error, e.g. timeout
socket.initialRemoteAddress!, // Recorded by certCB monkeypatch
tags: []
});
tlsClientErrorListener(socket, buildTlsError(socket, getCauseFromError(error)));
});

@@ -228,3 +254,3 @@

socket.write('HTTP/' + req.httpVersion + ' 200 OK\r\n\r\n', 'utf-8', () => {
socket.__timingInfo!.tunnelSetup = Date.now();
socket.__timingInfo!.tunnelSetupTimestamp = now();
server.emit('connection', socket);

@@ -231,0 +257,0 @@ });

@@ -62,6 +62,19 @@ /**

remoteIpAddress: string;
remotePort: number;
failureCause: 'closed' | 'reset' | 'cert-rejected' | 'no-shared-cipher' | 'unknown';
tags: string[];
timingEvents: TlsTimingEvents;
}
export interface TlsTimingEvents {
startTime: number; // Ms since unix epoch
// High-precision floating-point monotonically increasing timestamps.
// Comparable and precise, but not related to specific current time.
connectTimestamp: number; // When the socket initially connected
failureTimestamp: number; // When the error occurred
handshakeTimestamp?: number; // When the handshake completed (if it did)
tunnelTimestamp?: number; // When the outer tunnel was create (if present)
}
// Internal representation of an ongoing HTTP request whilst it's being processed

@@ -68,0 +81,0 @@ export interface OngoingRequest extends Request, EventEmitter {

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc