Skip to content

Commit

Permalink
Merge pull request #664 from Travelport-Ukraine/master
Browse files Browse the repository at this point in the history
1.17.2 Handling of SOAP:Fault errors coming with 500 codes
  • Loading branch information
dchertousov authored Sep 18, 2024
2 parents 446ca3a + 6d5770c commit 0026375
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 55 deletions.
20 changes: 11 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "uapi-json",
"version": "1.17.1",
"version": "1.17.2",
"description": "Travelport Universal API",
"main": "src/",
"files": [
Expand Down
93 changes: 52 additions & 41 deletions src/Request/uapi-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,61 +75,71 @@ module.exports = function uapiRequest(
return reqType;
}));

const sendRequest = function (xml) {
const sendRequest = async (xml) => {
if (debugMode) {
log('Request URL: ', service);
log('Request XML: ', pd.xml(xml));
}
return axios.request({
url: service,
method: 'POST',
timeout: config.timeout || 5000,
auth: {
username: auth.username,
password: auth.password,
},
headers: {
'Accept-Encoding': 'gzip',
'Content-Type': 'text/xml',
},
data: xml,
})
.then((response) => {
if (debugMode) {
log('Response SOAP: ', pd.xml(response.data));
}
return response.data;
})
.catch((e) => {
const rsp = e.response;

if (['ECONNREFUSED', 'ECONNRESET'].includes(e.code)) {
return Promise.reject(new RequestRuntimeError.UAPIServiceError(e));
}
try {
const response = await axios.request({
url: service,
method: 'POST',
timeout: config.timeout || 5000,
auth: {
username: auth.username,
password: auth.password,
},
headers: {
'Accept-Encoding': 'gzip',
'Content-Type': 'text/xml',
},
data: xml,
});

if (['ECONNABORTED'].includes(e.code)) {
return Promise.reject(new RequestRuntimeError.UAPIServiceTimeout(e));
}
if (debugMode) {
log('Response SOAP: ', pd.xml(response.data));
}

if (!rsp) {
if (debugMode) {
log('Unexpected Error: ', pd.json(e));
}
return response.data;
} catch (e) {
const rsp = e.response;

return Promise.reject(new RequestSoapError.SoapUnexpectedError(e));
if (['ECONNREFUSED', 'ECONNRESET'].includes(e.code)) {
throw new RequestRuntimeError.UAPIServiceError(e);
}

if (['ECONNABORTED'].includes(e.code)) {
throw new RequestRuntimeError.UAPIServiceTimeout(e);
}

if (!rsp) {
if (debugMode) {
log('Unexpected Error: ', pd.json(e));
}

const error = {
status: rsp.status,
data: rsp.data,
};
throw new RequestSoapError.SoapUnexpectedError(e);
}

// TVPT error response with 500 header
if (rsp.data.toUpperCase().includes('SOAP:FAULT')) {
if (debugMode) {
log('Error Response SOAP: ', pd.json(error));
log('Response SOAP: ', pd.xml(rsp.data));
}
return rsp.data;
}

return Promise.reject(new RequestSoapError.SoapRequestError(error));
});
const error = {
status: rsp.status,
data: rsp.data,
};

if (debugMode) {
log('Error Response SOAP: ', pd.json(error));
}

throw new RequestSoapError.SoapRequestError(error);
}
};

const parseResponse = function (response, parseParams) {
Expand All @@ -146,6 +156,7 @@ module.exports = function uapiRequest(
};

const validateSOAP = function (parsedXML) {
console.log(parsedXML);
if (parsedXML['SOAP:Fault']) {
if (debugMode > 2) {
log('Parsed error response', pd.json(parsedXML));
Expand Down
56 changes: 53 additions & 3 deletions test/Request/Request.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const { expect } = chai;
chai.use(sinonChai);

const templates = require('../../src/Services/Air/templates');
const terminalTemplates = require('../../src/Services/Terminal/templates');
const config = require('../testconfig');

const errorXML = fs.readFileSync(path.join(
__dirname,
Expand Down Expand Up @@ -119,7 +121,6 @@ describe('#Request', () => {
expect(console.log).to.have.callCount(6);
});
});

it('should test custom log function with success', () => {
const log = sinon.spy((...args) => {
console.log(args);
Expand All @@ -133,7 +134,6 @@ describe('#Request', () => {
expect(log).to.have.callCount(6);
});
});

it('should test custom log function with error', () => {
const log = sinon.spy((...args) => {
console.log(args);
Expand All @@ -147,7 +147,6 @@ describe('#Request', () => {
expect(log).to.have.callCount(6);
});
});

it('should test result of parser as string', () => {
const log = sinon.spy((...args) => {
console.log(args);
Expand All @@ -163,5 +162,56 @@ describe('#Request', () => {
expect(log).to.have.callCount(6);
});
});
it('should handle SOAP:Fault in case when sent with 500 header', async () => {
const uapiRequest = proxyquire('../../src/Request/uapi-request', {
axios: {
request: async () => {
const error = new Error('Request failed with status code 500');
error.response = {
status: 500,
data: '<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"><SOAP:Body><SOAP:Fault><faultcode>Server.System</faultcode><faultstring>String index out of range: 6</faultstring><detail><common_v33_0:ErrorInfo xmlns:common_v33_0="http://www.travelport.com/schema/common_v33_0"><common_v33_0:Code>1</common_v33_0:Code><common_v33_0:Service>SYSTEM</common_v33_0:Service><common_v33_0:Type>System</common_v33_0:Type><common_v33_0:Description>Unexpected system error.</common_v33_0:Description><common_v33_0:TransactionId>8D8D39030A0E7DE522FBC89CC3DAC930</common_v33_0:TransactionId></common_v33_0:ErrorInfo></detail></SOAP:Fault></SOAP:Body></SOAP:Envelope>',
};
throw error;
},
},
});

const errorHandler = sinon.mock().resolves({ error: 'handled' });

const uapiRequestParams = [
'URL',
config,
terminalTemplates.request,
null,
(params) => params,
errorHandler,
(res) => res,
true,
];

const request = uapiRequest(...uapiRequestParams);
const requestParams = {
sessionToken: 'SESSION_TOKEN',
command: 'ER',
};

const res = await request(requestParams);
expect(res).to.deep.equal({ error: 'handled' });

expect(errorHandler).to.be.calledOnceWith({
faultcode: 'Server.System',
faultstring: 'String index out of range: 6',
detail: {
'common_v33_0:ErrorInfo': {
'common_v33_0:Code': '1',
'common_v33_0:Service': 'SYSTEM',
'common_v33_0:Type': 'System',
'common_v33_0:Description': 'Unexpected system error.',
'common_v33_0:TransactionId': '8D8D39030A0E7DE522FBC89CC3DAC930',
'xmlns:common_v33_0': 'http://www.travelport.com/schema/common_v33_0'
}
}
});
});
});
});
2 changes: 1 addition & 1 deletion test/Terminal/Terminal.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ describe('#Terminal', function terminalTest() {
});
});
});
describe.only('Handling uapi errors', () => {
describe('Handling uapi errors', () => {
beforeEach(() => {
// Resetting spies
getSessionToken.resetHistory();
Expand Down

0 comments on commit 0026375

Please sign in to comment.