I am trying to make a SOAP call over HTTPS. Normally I'm doing this from Azure, which works fine, but I'm developing a new module and need to call it locally through our corporate proxy. If I just make the call normally, I get a SELF_SIGNED_CERTIFICATE_IN_CHAIN
error message. In some cases I've been able to get around this using the https-proxy-agent
module, but when I set it up as below, I am getting the error message getaddrinfo ENOTFOUND undefined undefined:80
. I am sure that the proxy URL is valid. As I debugged the call, I could see the proxy information being passed to the call (initiating SOAP call via easy-soap-request
, which in turn makes http calls via axios
). Here are some relevant code snippets:
const soapRequest = require('easy-soap-request');
let httpsProxyAgent = require('https-proxy-agent');
var agent = new httpsProxyAgent({hostname:'proxy.address.com', port:8080, rejectUnauthorized:false});
// Next lines are within the class of my helper function
await (async () => {
var response = {};
try {
console.log('Converting catalog number...');
console.log(url);
response = await soapRequest(url, headers, requestXML, 10000, {httpsAgent:agent});
} catch (err) {
console.log(`Error converting catalog number: ${err}`);
processObj.message = 'SERVICE_DOWN';
processObj.error = err.message;
return;
}
// Then do some more stuff with the response, but I don't get this far
The easy-soap-request module itself doesn't really seem to be doing much. Makes me wonder why I don't just do a post with request-promise-native
(which I use for all my other API calls), but I suppose that's beside the point. Here is the easy-soap-request module for reference. The only thing I noticed is that it's actually using axios-https-proxy-fix
instead of axios
.
const axios = require('axios-https-proxy-fix');
module.exports = function soapRequest(url, headers, xml, timeout = 10000, proxy = false) {
return new Promise((resolve, reject) => {
axios({
method: 'post',
url,
headers,
data: xml,
timeout,
proxy,
}).then((response) => {
resolve({
response: {
headers: response.headers,
body: response.data,
statusCode: response.status,
},
});
}).catch((error) => {
if (error.response) {
console.error(`SOAP FAIL: ${error}`);
reject(error.response.data);
} else {
console.error(`SOAP FAIL: ${error}`);
reject(error);
}
});
});
};
It seems my comment about that easy-soap-request
not actually adding much value proved to be correct. I was easily able to use request-promise-native
as a drop-in replacement. And because the latter respects my .env proxy variable, I didn't need to use an httpsAgent either. I still had to add rejectUnauthorized:false
to the options. Here is the updated code, with the original line commented out:
//const soapRequest = require('easy-soap-request');
//let httpsProxyAgent = require('https-proxy-agent');
//var agent = new httpsProxyAgent({hostname:'proxy.address.com', port:8080, rejectUnauthorized:false});
const request = require('request-promise-native');
// Next lines are within the class of my helper function
await (async () => {
var response = {};
try {
console.log('Converting catalog number...');
console.log(url);
//response = await soapRequest(url, headers, requestXML, 10000, {httpsAgent:agent});
response = await request({
url: url,
method: 'POST',
headers: headers,
body: requestXML,
rejectUnauthorized: false
})
} catch (err) {
console.log(`Error converting catalog number: ${err}`);
processObj.message = 'SERVICE_DOWN';
processObj.error = err.message;
return;
}
Works like a charm! I'm actually going to go back and update my other integration modules to use this method instead of easy-soap-request
throughout the application.