@apistudio/apim-cli
Version:
CLI for API Management Products
188 lines (176 loc) • 6.24 kB
text/typescript
/**
* Copyright IBM Corp. 2024, 2025
*/
import axios from 'axios';
import FormData from 'form-data';
import { GatewaysJson, IpcError, Logger } from '@apic/studio-shared';
import { AppConstants } from '../constants/app-constants.js';
export const sendToGateway = async (
gatewayURL: string,
gatewayUser: string,
gatewaySecret: string,
is_mcsp_enabled: boolean,
zipBuffer: Buffer,
gatewaysJsonContent: GatewaysJson
) => {
const formData = new FormData();
formData.append('file', zipBuffer, 'gatewayInstance.zip');
formData.append('overwrite', gatewaysJsonContent.overwrite);
let authorizationHeader;
if (is_mcsp_enabled) {
authorizationHeader = `Bearer ${gatewaySecret}`;
} else {
const credentials = `${gatewayUser}:${gatewaySecret}`;
const encodedCredentials = Buffer.from(credentials).toString('base64');
authorizationHeader = `Basic ${encodedCredentials}`;
}
return axios
.post(gatewayURL + AppConstants.DEPLOY_GATEWAY_URL, formData, {
headers: {
...formData.getHeaders(),
Authorization: authorizationHeader,
},
})
.then((response) => {
Logger.debug('Gateway deployment response received', {
data: JSON.stringify(response.data),
});
const processedResponse = ParseAndFindResponse(response);
if (processedResponse && processedResponse.length) {
return {
success: false,
statusCode: response.status,
message: 'Api deployment Failed',
data: response.data,
errors: processedResponse,
};
}
return {
success: true,
statusCode: response.status,
message: 'Api deployment Successful',
data: response.data,
errors: [],
};
})
.catch((error) => {
let errorMessage =
error.response?.data?.errorDetails ?? `Response sending to ${gatewayURL}: ${error.message}`;
let statusCode = error.response ? error.response.status : 404;
let errors = [errorMessage];
// Add error logging
Logger.error(
'Gateway deployment failed',
error instanceof Error ? error : new Error(String(error)),
{ gatewayURL, context: 'Gateway Deployment' }
);
if (statusCode === 401) {
errorMessage = 'Unauthorized: Invalid credentials';
statusCode = 401;
errors = ['Unauthorized access: Please check your authentication details.'];
}
return {
success: false,
statusCode,
message: errorMessage,
data: null,
errors,
};
});
};
export async function validationManager(url: string, authorizationHeader: string) {
return axios
.get(url, {
timeout: 20000,
headers: {
Authorization: authorizationHeader,
},
})
.then((res) => {
Logger.debug('Gateway validation response', { data: res.data });
if (res.status === 200) {
return { data: 'OK', status: 200 };
} else {
Logger.warn(`Unexpected status code: ${res.status}`, {
context: 'Validation',
});
throw new IpcError(res.data, res.status);
}
})
.catch((err) => {
if (err.response) {
const status = err.response.status;
const errorData = err.response.data;
if (status === 401) {
Logger.error('The user name or password did not match.', err, {
context: 'Authorization',
});
throw new IpcError('The user name or password did not match.', 401, errorData);
} else if (status === 502) {
Logger.error('Bad Gateway.', err, { context: 'Validation' });
throw new IpcError('Bad Gateway', 502);
} else if (status === 404) {
Logger.error('Gateway not found.', err, { context: 'Validation' });
throw new IpcError('Gateway not found', 404);
} else {
Logger.error(`Validation failed with status: ${status}`, err, {
context: 'Validation',
errorData,
});
throw new IpcError(errorData, status);
}
} else if (err.code === 'ECONNABORTED') {
Logger.error('Request timed out.', err, { context: 'Validation' });
throw new IpcError('Request timed out', 408);
} else if (
err.message?.includes('SSL') ||
err.message?.includes('certificate') ||
err.code === 'ERR_SSL_CERT'
) {
Logger.error('SSL certificate validation failed.', err, { context: 'Validation' });
throw new IpcError(
'SSL certificate validation failed.',
495,
'SSL certificate validation failed.'
);
} else if (err.code === 'ENOTFOUND') {
Logger.error('Error: Could not resolve host name', err, { context: 'Validation' });
throw new IpcError(
'Error: Could not resolve host name',
404,
'Error: Could not resolve host name'
);
} else if (err.code === 'ECONNREFUSED') {
Logger.error(
'Error: Gateway refused to connect. Please verify the service availability.',
err,
{ context: 'Validation' }
);
throw new IpcError(
'Error: Gateway refused to connect. Please verify the service availability.',
503,
'Error: Gateway refused to connect. Please verify the service availability.'
);
} else {
Logger.error('Gateway validation failed', err, { context: 'Validation' });
throw new IpcError('Something went wrong while validating the gateway.', 500);
}
});
}
export function ParseAndFindResponse(response: any) {
const failedExplanations: string[] = [];
if (response?.data?.StudioResult && Array.isArray(response.data.StudioResult)) {
for (const item of response.data.StudioResult) {
if (item && typeof item === 'object') {
const apiKey = Object.keys(item).find((key) => key.toLowerCase() === 'api');
if (apiKey && item[apiKey]) {
const api = item[apiKey];
if (api.status === 'Failed' && api.explanation) {
failedExplanations.push(api.explanation);
}
}
}
}
}
return failedExplanations;
}