async function create()

in apps/mountebank-mock/mountebank-source/src/models/imposter.js [57:220]


async function create (Protocol, creationRequest, baseLogger, config, isAllowedConnection) {
    function scopeFor (port) {
        let scope = `${creationRequest.protocol}:${port}`;

        if (creationRequest.name) {
            scope += ' ' + creationRequest.name;
        }
        return scope;
    }

    const logger = scopedLogger.create(baseLogger, scopeFor(creationRequest.port)),
        imposterState = {},
        unresolvedProxies = {},
        header = helpers.clone(creationRequest);

    // Free up the memory by allowing garbage collection of stubs when using filesystemBackedImpostersRepository
    delete header.stubs;

    let stubs;
    let resolver;
    let encoding;
    let numberOfRequests = 0;

    compatibility.upcast(creationRequest);

    // If the CLI --mock flag is passed, we record even if the imposter level recordRequests = false
    const recordRequests = config.recordRequests || creationRequest.recordRequests;

    async function findFirstMatch (request) {
        const filter = stubPredicates => {
                return stubPredicates.every(predicate =>
                    predicates.evaluate(predicate, request, encoding, logger, imposterState));
            },
            observePredicateMatchDuration = metrics.predicateMatchDuration.startTimer(),
            match = await stubs.first(filter);

        observePredicateMatchDuration({ imposter: logger.scopePrefix });
        if (match.success) {
            logger.debug(`using predicate match: ${JSON.stringify(match.stub.predicates || {})}`);
        }
        else {
            metrics.noMatchCount.inc({ imposter: logger.scopePrefix });
            logger.info('no predicate match, using default response');
        }
        return match;
    }

    async function recordMatch (stub, request, response, responseConfig, start) {
        if (response.proxy) {
            // Out of process proxying, so we don't have the actual response yet.
            const parts = response.callbackURL.split('/'),
                proxyResolutionKey = parts[parts.length - 1];

            unresolvedProxies[proxyResolutionKey] = {
                recordMatch: proxyResponse => {
                    return stub.recordMatch(request, proxyResponse, responseConfig, new Date() - start);
                }
            };
        }
        else if (response.response) {
            // Out of process responses wrap the result in an outer response object
            await stub.recordMatch(request, response.response, responseConfig, new Date() - start);
        }
        else {
            // In process resolution
            await stub.recordMatch(request, response, responseConfig, new Date() - start);
        }
    }

    // requestDetails are not stored with the imposter
    // It was created to pass the raw URL to maintain the exact querystring during http proxying
    // without having to change the path / query options on the stored request
    async function getResponseFor (request, requestDetails) {
        if (!isAllowedConnection(request.ip, logger)) {
            metrics.blockedIPCount.inc({ imposter: logger.scopePrefix });
            return { blocked: true, code: 'unauthorized ip address' };
        }

        const start = new Date();

        metrics.requestCount.inc({ imposter: logger.scopePrefix });
        numberOfRequests += 1;
        if (recordRequests) {
            await stubs.addRequest(request);
        }

        const match = await findFirstMatch(request),
            observeResponseGenerationDuration = metrics.responseGenerationDuration.startTimer(),
            responseConfig = await match.stub.nextResponse();

        logger.debug(`generating response from ${JSON.stringify(responseConfig)}`);
        const response = await resolver.resolve(responseConfig, request, logger, imposterState, requestDetails);
        observeResponseGenerationDuration({ imposter: logger.scopePrefix });

        if (config.recordMatches) {
            await recordMatch(match.stub, request, response, responseConfig, start);
        }
        return response;
    }

    async function getProxyResponseFor (proxyResponse, proxyResolutionKey) {
        const response = await resolver.resolveProxy(proxyResponse, proxyResolutionKey, logger, imposterState);
        if (config.recordMatches && unresolvedProxies[String(proxyResolutionKey)].recordMatch) {
            await unresolvedProxies[String(proxyResolutionKey)].recordMatch(response);
        }
        delete unresolvedProxies[String(proxyResolutionKey)];
        return response;
    }

    async function resetRequests () {
        await stubs.deleteSavedRequests();
        numberOfRequests = 0;
    }

    return new Promise((resolve, reject) => {
        try {
            if (!helpers.defined(creationRequest.host) && helpers.defined(config.host)) {
                creationRequest.host = config.host;
            }

            Protocol.createServer(creationRequest, logger, getResponseFor).then(server => {
                if (creationRequest.port !== server.port) {
                    creationRequest.port = server.port;
                    logger.changeScope(scopeFor(server.port));
                }
                logger.info('Open for business...');

                stubs = server.stubs;
                resolver = server.resolver;
                encoding = server.encoding;

                function stop () {
                    return new Promise(closed => {
                        server.close(() => {
                            logger.info('Ciao for now');
                            closed();
                        });
                    });
                }

                async function loadRequests () {
                    return recordRequests ? stubs.loadRequests() : [];
                }

                const printer = imposterPrinter.create(header, server, loadRequests),
                    toJSON = options => printer.toJSON(numberOfRequests, options);

                return resolve({
                    port: server.port,
                    url: '/imposters/' + server.port,
                    creationRequest: creationRequest,
                    toJSON,
                    stop,
                    getResponseFor,
                    getProxyResponseFor,
                    resetRequests
                });
            }, reject);
        }
        catch (error) {
            reject(error);
        }
    });
}