@n1k1t/mock-server
Version:
Powerful util to setup mocks over HTTP APIs
110 lines • 5.04 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 https_proxy_agent_1 = require("https-proxy-agent");
const lodash_1 = __importDefault(require("lodash"));
const logger_1 = require("../../../logger");
const models_1 = require("../../models");
const logger = logger_1.Logger.build('Server.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) {
return null;
}
logger.error('Got unexpected error while execution', error?.stack ?? error);
});
return context.complete();
}
async match(context) {
const expectation = context.provider.storages.expectations.match(context.snapshot);
if (!expectation && context.hasStatuses(['handling'])) {
context.assign({
outgoing: await this.reply(context, {
type: 'plain',
status: 404,
dataRaw: Buffer.from('Expectation was not found'),
headers: {},
}),
});
return null;
}
return expectation;
}
async forward(context, incoming, configuration) {
const options = await this
.compileForwardingConfiguration(context, incoming, configuration)
.catch((error) => {
context.snapshot.assign({
error: { code: 'UNKNOWN', message: error?.message ?? 'Unknown' },
outgoing: { type: 'plain', status: 502, headers: {} },
});
logger.error('Got error while execution [compileForwardingConfiguration] method', error?.stack ?? error);
throw error;
});
const response = await axios_1.default
.request(options)
.catch((error) => {
if (!error.response) {
context.snapshot.assign({
error: lodash_1.default.pick(error, ['message', 'code']),
outgoing: { type: 'plain', status: 502, headers: {} },
});
logger.error('Got error while forwaring', error?.stack ?? error);
throw error;
}
return error.response;
});
const type = (0, models_1.extractPayloadType)(response.headers) ?? 'plain';
const data = (0, models_1.parsePayload)(type, response.data);
return {
incoming,
outgoing: {
type: type,
status: response.status,
headers: response.headers,
data,
dataRaw: 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.dataRaw && { 'content-length': String(outgoing.dataRaw.length) }),
}), lodash_1.default.isNil);
context.response.writeHead(outgoing.status, outgoing.headers);
context.response.write(outgoing.dataRaw ?? '');
context.response.end();
return outgoing;
}
/** Compiles Axios request configuration to forward */
async compileForwardingConfiguration(context, incoming, configuration) {
const url = new URL(configuration.url ?? incoming.path, configuration.baseUrl);
const isSecured = url.protocol.includes('https');
return {
timeout: configuration.timeout ?? 30000,
method: incoming.method,
headers: Object.assign(incoming.headers, {
connection: 'close',
...(configuration.options?.overrideHost !== false && { host: url.host }),
...(incoming.dataRaw && { 'content-length': String(incoming.dataRaw.length) }),
}),
...(configuration.url && { url: configuration.url }),
...(configuration.baseUrl && { baseURL: configuration.baseUrl, url: incoming.path }),
data: incoming.dataRaw,
params: context.incoming.query,
responseType: 'arraybuffer',
...((configuration.proxy && !isSecured) && { proxy: configuration.proxy }),
...((configuration.proxy && isSecured) && {
httpsAgent: new https_proxy_agent_1.HttpsProxyAgent(`http://${configuration.proxy.host}:${configuration.proxy.port}`),
}),
};
}
}
exports.HttpExecutor = HttpExecutor;
//# sourceMappingURL=executor.js.map