Ville Miekk-oja Ville Miekk-oja - 3 months ago 47
Node.js Question

SOAP for NodeJS without using WSDL

I'm dealing with a web service that only supports SOAP. Also, I have a NodeJS application, from where I'm supposed to use this service through soap calls.

The biggest problem is, that the Web Service doesn't have a WSDL api description anywhere. So my question is, how could I with NodeJS, use Soap without WSDL? All the libraries I have checked for NodeJS so far require that I give them the WSDL url. I found one for C# that doesn't require, here: C#-soap-without-wsdl

Answer Source

I have also encountered this problem in the past. If you're like me, you've only worked with JSON and SOAP looks scary and frustrating. The good thing is that SOAP still uses HTTP to make requests. The only thing that is special is the way the body is formatted and the headers + header values.

After realizing this, the solution I eventually arrived at was to generate the few SOAP requests I needed using a desktop SOAP tool like SoapUI and then simply send these generated requests using a normal HTTP request library for node.

Here's an example that consistently worked for me:

// SOAP
var requestBody =
  '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ' +
  'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ><soap:Header>' +
  '<SOAPAction>addRoom' +
  '</SOAPAction></soap:Header><soap:Body><AddRoomRequest ' +
  'xmlns="http://portal.vidyo.com/admin/v1_1"><room><name>' +
  params.conferenceName + '</name><RoomType>Public</RoomType><ownerName>' +
  vidyoApiUsername  + '</ownerName>' + '<extension>' +
  params.conferenceExtension  +
  '</extension><groupName>Default</groupName><RoomMode><isLocked>' +
  'false</isLocked><hasPIN>false</hasPIN><hasModeratorPIN>false' +
  '</hasModeratorPIN></RoomMode></room></AddRoomRequest></soap:Body>' +
  '</soap:Envelope>';

var requestHeaders = {
  'cache-control': 'no-cache',
  'soapaction': 'addRoom',
  'content-type': 'text/xml;charset=UTF-8'
};

var requestOptions = {
  'method': 'POST',
  'url': vidyoApiEndpoint,
  'qs': { 'wsdl': ''},
  'headers': requestHeaders,
  'body': requestBody,
  'timeout': 5000
};

request(requestOptions, function (error, response, body) {
  if (error) {
    // handle error
  } else {
    try {
      var parsingOptions = {
        'object': true,
        'sanitize': false
      };
      var jsonResult = parser.toJson(body, parsingOptions); // from xml
      if(jsonResult['soapenv:Envelope']
        ['soapenv:Body']
        ['ns1:AddRoomResponse']
        ['ns1:OK'] === 'OK') {
          conferenceInfo(req, res, next, params);
      } else {
       // handle error
      }
    } catch (e) {
      // handle error
    }
   }
}).auth(vidyoApiUsername, vidyoApiPassword); 
// you can remove this .auth if your api has no authentication

UPDATE: The bottom line is that this is a workaround which helps explain to a beginner how SOAP works compared to other requests. This is not meant to be a recommendation as a best practice, but rather information which could help a developer understand the issue at hand.