Sending XML SOAP Requests In JavaScript

2020-10-15T10:00:00.000Z

0 views


Problem

  • You're faced with the task of making a SOAP request in Javascript.
  • The recommended NPM packages for SOAP requests are unfamiliar and don't work easily.

Solution

Use a tool you're familiar with, such as axios.

 
const xml = '<your_xml></your_xml>'
const soapURL = 'https://...'
 
try {
  const res = await axios.post(soapURL, xml, {
    headers: {
      'Accept-Encoding': 'gzip,deflate',
      'Content-Type': 'text/xml;charset=UTF-8', // These headers were taken from a successful request using the desktop application `SOAPUI`
      'SOAPAction': 'provider_soap_request_type', // this may be required or not, depending on the wsdl setup
    },
  });
} catch (e) {
  // Handle e...
}

In this example:

  • The soapURL & SOAPAction are set by the endpoint provider
  • The xml is the string form of the xml required for the request

There are multiple packages available to create XMLs from, and parse XMLs to, Javascript objects. I use a combination of xml2js & xmlbuilder.

  • xmlbuilder for creating
  • xml2js for parsing

Here's how you can create an xml using xmlbuilder:

const xml = xmlbuilder
  .begin()
  .ele({
    'soapenv:Envelope': {
      '@xmlns:soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',
      '@xmlns:api': 'your_provider_soap_api',
      'soapenv:Header': {},
      'soapenv:Body': {
        'api:your_soap_api_endpoint': {
          sessionId: '1234-XYY',
          userId: 123,
          ...,
        },
      },
    },
  })
  .end();

N.B. Find more about the specific syntax at https://www.npmjs.com/package/xmlbuilder

The exact keys required inside the soapenv:Body object depends on the xml nodes you need for your request, but it should look fairly similar to the above.

You can pass the xml created by xmlBuilder as the xml argument in the axios code above.

And when you get the response...

const parsedResponseToJS = await xml2js.parseStringPromise(res.data, { explicitArray: false, ignoreAttrs: true });

parsedResponseToJS will be a JS object representation of the XML response, ready for you to validate and use in your code.

Here's all that put together:

const buildXml = () => {
  return xmlbuilder
  .begin()
  .ele({
    'soapenv:Envelope': {
      '@xmlns:soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',
      '@xmlns:api': 'your_provider_soap_api',
      'soapenv:Header': {},
      'soapenv:Body': {
        'api:your_soap_api_endpoint': {
          sessionId: '1234-XYY',
          userId: 123,
          ...,
        },
      },
    },
  })
  .end();
}
 
const xml = buildXml()
const soapURL = 'https://myurl.com'
 
const res = await axios.post(soapURL, xml, {
  headers: {
    'Accept-Encoding': 'gzip,deflate',
    'Content-Type': 'text/xml;charset=UTF-8', // These headers were taken from a successful request using the desktop application `SOAPUI`
    'SOAPAction': 'provider_soap_request_type', // this may be required or not, depending on the wsdl setup
  },
}).catch(e => {
  // Some error handling and logging
});
 
const parsedResponseToJS = await xml2js.parseStringPromise(res.data, { explicitArray: false, ignoreAttrs: true });
 

Problem Solved?

If you have any questions you'd like to ask me about this post, feel free to reach me on Twitter or Github.

If you found this post useful and would like to show you're appreciation, feel free to send me a tip via the Brave Browser.