@n1k1t/mock-server
Version:
The ultimate toolkit to intercept, transform, and simulate HTTP/WS traffic with type-safe expectations
129 lines • 5.76 kB
JavaScript
;
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