ang-soap
Version:
SOAP client
166 lines (150 loc) • 6.1 kB
JavaScript
const _ = require('lodash');
const https = require('https');
const axios = require('axios');
const xmlParser = require('fast-xml-parser');
const jsonPathFinding = require('jsonpath');
const JsonParser = require('fast-xml-parser').j2xParser;
const defaultOptions = require('./config').defaultOptions;
const {errorMessages, debugMessages,encoding} = require('./config/constants');
/**
* This function uses axios http client to perform request.
* @param options
* @returns {Promise<AxiosResponse<any>>}
*/
const performHttpRequest = async (options) => {
let response;
try {
response = await axios(options.axios);
} catch (error) {
throw error;
}
return response;
};
/**
* This is the main function. It is used to create a new instance of ang-soap
* @param options
* @constructor
*/
function SoapClient(options) {
this.options = _.merge(defaultOptions, options);
}
/**
* This method calculates and sets Authorisation Http header
* @param username
* @param password
*/
SoapClient.prototype.setBasicAuthSecurity = function (username, password) {
const token = Buffer.from(`${username}:${password}`, encoding.utf8).toString(encoding.base64);
this.options.axios.headers.Authorization = `${encoding.basic} ${token}`;
};
/**
* This method disable SSL when performing an axios request
*/
SoapClient.prototype.disableSSL = function () {
this.options.axios.httpsAgent = new https.Agent({rejectUnauthorized: false});
};
/**
* This method enable SSL when performing an axios request
* By default SSL is enabled
*/
SoapClient.prototype.enableSSL = function () {
this.options.fastXmlParser.httpsAgent = new https.Agent({rejectUnauthorized: true});
};
/**
* By default,arrayMode is false. A tag with single occurrence is parsed as an object but as an array in case of multiple occurences.
* If you need to parse a specific tag as array only, you can use this method. Example of value: `/^yourTagName$/`
* @param value
*/
SoapClient.prototype.setArrayMode = function (value) {
this.options.fastXmlParser.xmlParser.arrayMode = value;
};
/**
* When you call multiple SOAP methods, each response probably has its own data structure.
* So if you use the jsonPath option, you may need to set it before performing each request.
* Example of JsonPath: `$..Envelope.Body.YourTargetObject`
* @param value
*/
SoapClient.prototype.setJsonPath = function (value) {
this.options.jsonPath = value;
};
/**
* This methods gets the request parameters and :
* 1 - Parse the request body from JSON to XML
* 2 - Perform the http call using axios
* 3 - Parse the response from XML to JSON
* 4 - Logs all the previous steps when debug is enabled.
* @param soapUrl
* @param jsonData
* @returns {Promise<*|T>}
*/
SoapClient.prototype.performRequest = async function (soapUrl, jsonData) {
const debug = this.options.debug;
const isRequestDataXML = this.options.isRequestDataXML;
const isResponseXML = this.options.isResponseXML;
let httpResponse, convertedJson;
this.options.axios.url = soapUrl;
// If isRequestDataXML option is true we do not parse JSON to XML
if (isRequestDataXML) {
this.options.axios.data = jsonData;
} else {
try {
// Use use fast-xml-parser to parse JSON to XML
const jsonParser = new JsonParser(this.options.fastXmlParser.jsonParser);
const xml = jsonParser.parse(jsonData);
debug && console.log(debugMessages.xmlRequestBody, xml);
this.options.axios.data = xml;
} catch (error) {
const parsingError = {message: errorMessages.convertingJsontoXml, error};
debug && console.log(debugMessages.parsingError, parsingError);
throw parsingError;
}
}
// Once the request body is parsed, perform the http request
try {
httpResponse = await performHttpRequest(this.options);
debug && console.log(debugMessages.httpResponse, httpResponse);
} catch (error) {
const axiosError = {message: errorMessages.performingHttpRequest, error};
debug && console.log(debugMessages.axiosError, axiosError);
throw axiosError;
}
// if isResponseXML option is true, we do not parse the response to JSON
if (isResponseXML) {
return httpResponse.data;
} else {
try {
// Use use fast-xml-parser to parse XML to JSON
convertedJson = xmlParser.parse(httpResponse.data, this.options.fastXmlParser.xmlParser);
debug && console.log(debugMessages.convertedJson, convertedJson);
if (!convertedJson) {
const error = Error(errorMessages.emptyResult);
const parsingError = {message: '', error};
debug && console.log(debugMessages.parsingError, parsingError);
throw parsingError;
}
} catch (error) {
const parsingError = {message: errorMessages.convertingXmlToJson, error};
debug && console.log(debugMessages.parsingError, parsingError);
throw parsingError;
}
const jsonPath = this.options.jsonPath;
if (jsonPath) {
try {
const targetJson = jsonPathFinding.value(convertedJson, jsonPath);
debug && console.log(debugMessages.targetJson, targetJson);
if (!targetJson) {
const error = Error(errorMessages.emptyResult);
const jsonPathError = {message: errorMessages.targetObjectNotFound, error};
debug && console.log(debugMessages.jsonPathError, jsonPathError);
throw jsonPathError;
}
return targetJson;
} catch (error) {
const jsonPathError = {message:errorMessages.findingTheTargetObject , error};
debug && console.log(debugMessages.jsonPathError, jsonPathError);
throw jsonPathError;
}
} else return convertedJson;
}
};
module.exports = SoapClient;