piral-cli
Version:
The standard CLI for creating and building a Piral instance or a Pilet.
260 lines • 8.97 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAxiosOptions = getAxiosOptions;
exports.getCertificate = getCertificate;
exports.getAuthorizationHeaders = getAuthorizationHeaders;
exports.getDefaultAgent = getDefaultAgent;
exports.getAgent = getAgent;
exports.downloadFile = downloadFile;
exports.createAxiosForm = createAxiosForm;
exports.handleAxiosError = handleAxiosError;
exports.postData = postData;
exports.postForm = postForm;
exports.postFile = postFile;
const path_1 = require("path");
const https_1 = require("https");
const os_1 = require("os");
const fs_1 = require("fs");
const log_1 = require("./log");
const config_1 = require("./config");
const info_1 = require("./info");
const io_1 = require("./io");
const interactive_1 = require("./interactive");
const external_1 = require("../external");
function getMessage(body) {
if (typeof body === 'string') {
try {
const content = JSON.parse(body);
return content.message;
}
catch (ex) {
return body;
}
}
else if (body && typeof body === 'object') {
if ('message' in body) {
return body.message;
}
else {
return JSON.stringify(body);
}
}
return '';
}
function streamToFile(source, target) {
const dest = (0, fs_1.createWriteStream)(target);
return new Promise((resolve, reject) => {
source.pipe(dest);
source.on('error', (err) => reject(err));
dest.on('finish', () => resolve([target]));
});
}
function getAxiosOptions(url) {
const auth = config_1.config.auth?.[url];
switch (auth?.mode) {
case 'header':
return {
headers: {
[auth.key]: auth.value,
},
};
case 'http':
return {
auth: {
username: auth.username,
password: auth.password,
},
};
default:
return {};
}
}
async function getCertificate(cert = config_1.config.cert) {
(0, log_1.log)('generalDebug_0003', 'Checking if certificate exists.');
if (await (0, io_1.checkExists)(cert)) {
const dir = (0, path_1.dirname)(cert);
const file = (0, path_1.basename)(cert);
(0, log_1.log)('generalDebug_0003', `Reading certificate file "${file}" from "${dir}".`);
return await (0, io_1.readBinary)(dir, file);
}
return undefined;
}
function getAuthorizationHeaders(scheme, key) {
if (key) {
switch (scheme) {
case 'basic':
return {
authorization: `Basic ${key}`,
};
case 'bearer':
return {
authorization: `Bearer ${key}`,
};
case 'digest':
return {
authorization: `Digest ${key}`,
};
case 'none':
default:
return {
authorization: key,
};
}
}
return {};
}
async function getDefaultAgent() {
const ca = await getCertificate();
const allowSelfSigned = config_1.config.allowSelfSigned;
return getAgent({ ca, allowSelfSigned });
}
function getAgent({ allowSelfSigned, ca }) {
if (ca) {
return new https_1.Agent({ ca });
}
else if (allowSelfSigned) {
return new https_1.Agent({ rejectUnauthorized: false });
}
else {
return undefined;
}
}
function downloadFile(target, httpsAgent) {
return external_1.axios
.get(target, {
responseType: 'stream',
headers: info_1.standardHeaders,
httpsAgent,
})
.then((res) => {
const rid = Math.random().toString(36).split('.').pop();
const target = (0, path_1.join)((0, os_1.tmpdir)(), `pilet_${rid}.tgz`);
(0, log_1.log)('generalDebug_0003', `Writing the downloaded file to "${target}".`);
return streamToFile(res.data, target);
})
.catch((error) => {
(0, log_1.log)('failedHttpGet_0068', error.message);
return [];
});
}
function createAxiosForm(formData) {
const form = new external_1.FormData();
Object.keys(formData).forEach((key) => {
const value = formData[key];
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
form.append(key, value);
}
else if (Array.isArray(value)) {
form.append(key, value[0], value[1]);
}
else {
// unknown value - skip for now
}
});
return form;
}
function handleAxiosError(error, interactive, httpsAgent, refetch, onfail) {
if (!onfail) {
onfail = () => {
throw error;
};
}
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
const { data, statusText, status } = error.response;
if (interactive && 'interactiveAuth' in data) {
const { interactiveAuth } = data;
if (typeof interactiveAuth === 'string') {
(0, log_1.log)('generalDebug_0003', `Received status "${status}" from HTTP - trying interactive log in to "${interactiveAuth}".`);
return (0, interactive_1.getTokenInteractively)(interactiveAuth, httpsAgent).then(({ mode, token }) => refetch(mode, token));
}
}
const message = getMessage(data) || '';
return onfail(status, statusText, message);
}
else if (error.isAxiosError) {
// axios initiated error: try to parse message from error object
let errorMessage = error.errno || 'Unknown Axios Error';
if (typeof error.toJSON === 'function') {
const errorObj = error.toJSON();
errorMessage = errorObj?.message ?? errorMessage;
}
return onfail(500, undefined, errorMessage);
}
else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
return onfail(500, undefined, error.request);
}
else {
// Something happened in setting up the request that triggered an Error
return onfail(500, undefined, error.message);
}
}
function createPayload(data, scheme, key, customHeaders, isForm) {
if (isForm) {
const form = createAxiosForm(data);
const extraHeaders = form.getHeaders();
const headers = {
...info_1.standardHeaders,
...customHeaders,
...getAuthorizationHeaders(scheme, key),
...extraHeaders,
};
return [form, headers];
}
else {
const headers = {
...info_1.standardHeaders,
...customHeaders,
...getAuthorizationHeaders(scheme, key),
};
return [data, headers];
}
}
async function postData(target, scheme, key, data, customHeaders = {}, httpsAgent = undefined, isForm = false, interactive = false) {
try {
const [body, headers] = createPayload(data, scheme, key, customHeaders, isForm);
const res = await external_1.axios.post(target, body, {
headers,
httpsAgent,
maxContentLength: Infinity,
maxBodyLength: Infinity,
});
return {
status: res.status,
success: true,
response: res.data,
};
}
catch (error) {
return await handleAxiosError(error, interactive, httpsAgent, (mode, token) => postData(target, mode, token, data, customHeaders, httpsAgent, isForm, false), (status, statusText, response) => {
if (status === 500) {
(0, log_1.log)('failedHttpPost_0065', response);
return {
status: 500,
success: false,
response: undefined,
};
}
else {
(0, log_1.log)('unsuccessfulHttpPost_0066', statusText, status, response);
return {
status,
success: false,
response,
};
}
});
}
}
function postForm(target, scheme, key, formData, customHeaders = {}, httpsAgent = undefined, interactive = false) {
return postData(target, scheme, key, formData, customHeaders, httpsAgent, true, interactive);
}
function postFile(target, scheme, key, file, customFields = {}, customHeaders = {}, agent = undefined, interactive = false) {
const data = { ...customFields, file: [file, 'pilet.tgz'] };
return postForm(target, scheme, key, data, customHeaders, agent, interactive);
}
//# sourceMappingURL=http.js.map