0

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);
      }
    });
  });
};
billoverton
  • 2,705
  • 2
  • 9
  • 32

2 Answers2

0

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.

billoverton
  • 2,705
  • 2
  • 9
  • 32
0

Test success using version 4.1.3. You were sending parameters to Axios in a wrong way

replace:

let httpsProxyAgent = require('https-proxy-agent');
var agent = new httpsProxyAgent({hostname:<>, port:<>, rejectUnauthorized:false});

with: var proxy = {host:<>, port:<>};

and: const { response } = await soapRequest({ url: url, headers: sampleHeaders, xml: xml, timeout: 1000000, proxy: {httpsAgent: agent }});

with const { response } = await soapRequest({ url: url, headers: sampleHeaders, xml: xml, timeout: 1000000, proxy});

The documentation of the library should be updated since it shows no way to use proxy.

At the time of your question: There was an issue related to Axios proxy not working, but was closed a year before you made your question: https://github.com/axios/axios/issues/2072#

The use of proxyagent was proposed as a workaround then, see one answer here: How to use axios with a proxy server to make an https call?

Considering that answer, you had to replace 'hostname' with 'host' in proxyAgent definition in order to make your code to work.

  • 1
    To be clear, the axios call was part of the `easy-soap-request` module, not something in my code. They may have updated the module since then, though since the module doesn't seem to do anything a regular HTTP call can't, I didn't and still don't see any reason to use that module. – billoverton Jun 10 '21 at 19:52
  • The call is part of the `easy-soap-request` module, but the parameters being sent are part of the `axios` library. Your solution can lead others to errors. If it is a problem in old library versions, or you using the wrong parameters in newer versions, is the minor of the problems. At least be grateful. – Manuel de la Iglesia Campos Jun 23 '21 at 15:49
  • So you are saying that `easy-soap-request` v4.1.3 has fixed the issue? I just want to clarify here because it seemed you were suggesting that something in my code was making an incorrect call. "Upgrading to 4.1.3" would be a solution to my question, but changing the Axios call would not. Sorry if you felt I was ungrateful, it's just that I have no control over the content or documentation for `easy-soap-request`. If there is some value to continuing to use the module for some, fine, but for my issue making the call directly is all I needed (Axios would be preferred due to request deprecation) – billoverton Jun 23 '21 at 20:25