UNPKG

@n1k1t/mock-server

Version:

The ultimate toolkit to intercept, transform, and simulate HTTP/WS traffic with type-safe expectations

129 lines 5.76 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.HttpExecutor = void 0; const axios_1 = __importDefault(require("axios")); const lodash_1 = __importDefault(require("lodash")); const https_proxy_agent_1 = require("https-proxy-agent"); const http_encoding_1 = require("http-encoding"); const utils_1 = require("../../../utils"); const utils_2 = require("../../utils"); const logger_1 = require("../../../logger"); const models_1 = require("../../models"); const logger = logger_1.Logger.build('Transports.Http.Executor'); class HttpExecutor extends models_1.Executor { async exec(context, options) { await super.exec(context, options).catch((error) => { if (error instanceof models_1.ExecutorManualError && error.is('ECONNABORTED')) { return context.request.socket.destroy(); } logger.error('Got unexpected error while execution', error?.stack ?? error); }); return context.complete(); } async match(context) { const expectation = await context.provider.storages.expectations.match(context.snapshot); if (!expectation && context.is(['handling'])) { context.assign({ outgoing: await this.reply(context, { type: 'plain', status: 404, headers: { 'content-type': 'text/plain', }, raw: { data: Buffer.from('Expectation was not found'), }, }), }); return null; } return expectation; } async forward(context, incoming, schema) { const configuration = await this .compileForwardingConfiguration(context, incoming, schema) .catch((error) => { context.snapshot.assign({ error: { code: 'UNKNOWN', message: error?.message ?? 'Unknown' }, outgoing: { type: 'plain', status: 502, headers: {}, raw: {} }, }); logger.error('Got error while execution [compileForwardingConfiguration] method', error?.stack ?? error); throw error; }); const response = await axios_1.default .request(configuration) .catch(async (error) => { if (!error.response) { context.snapshot.assign({ error: lodash_1.default.pick(error, ['message', 'code']), outgoing: { type: 'plain', status: 502, headers: {}, raw: {} }, }); logger.error('Got error while forwaring', error?.stack ?? error); throw error; } return error.response; }); if (response.headers['content-encoding']) { response.data = await (0, http_encoding_1.decodeBuffer)(response.data, response.headers['content-encoding']); response.headers['content-encoding'] = 'utf-8'; } const parsed = response.data?.length ? (0, utils_2.parsePayload)(response.data, (0, models_1.definePayloadType)(response.headers) ?? 'plain') : null; return { schema, incoming, outgoing: { type: parsed?.type ?? 'plain', data: parsed?.data ?? undefined, status: response.status, headers: response.headers, raw: { data: response.data, }, }, }; } async reply(context, outgoing) { outgoing.headers = lodash_1.default.omitBy(Object.assign(lodash_1.default.omit(outgoing.headers, ['transfer-encoding']), { 'content-type': outgoing.headers['content-type'] ?? (outgoing.type === 'json' ? 'application/json' : outgoing.type === 'xml' ? 'application/xml' : undefined), ...(outgoing.raw.data && { 'content-length': String(outgoing.raw.data.length) }), }), lodash_1.default.isNil); context.response.writeHead(outgoing.status, outgoing.headers); context.response.write(outgoing.raw.data ?? Buffer.from('')); context.response.end(); return outgoing; } /** Compiles Axios request configuration to forward */ async compileForwardingConfiguration(context, incoming, schema) { const url = new URL(schema.url ?? incoming.path, schema.baseUrl); const isSecured = url.protocol.includes('https'); return { timeout: schema.timeout ?? 30000, method: incoming.method, headers: (0, utils_1.formatHeaders)(Object.assign(incoming.headers, { connection: 'close', ...(schema.options?.overrideHost !== false && { host: url.host }), ...(incoming.raw.data && { 'content-length': String(incoming.raw.data.length) }), })), ...(schema.url && { url: schema.url }), ...(schema.baseUrl && { baseURL: schema.baseUrl, url: incoming.path }), responseType: 'arraybuffer', params: context.incoming.query, data: incoming.raw.data, ...((schema.proxy && !isSecured) && { proxy: schema.proxy }), ...((schema.proxy && isSecured) && { httpsAgent: new https_proxy_agent_1.HttpsProxyAgent(`http://${schema.proxy.host}:${schema.proxy.port}`), }), }; } } exports.HttpExecutor = HttpExecutor; //# sourceMappingURL=executor.js.map