node.jssoapwsdlnode-soap

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


Solution

  • I have also encountered this problem in the past. It is especially difficult for developers with experience using mostly RESTful APIs to grok the fundamentals of SOAP in a reasonable amount of time, let alone be able to debug issues in it. The thing to keep in mind is that SOAP uses the exact same application layer protocol (HTTP) as the RESTful APIs you're probably used to working with. There will be headers, a uri, a method just like what you're used to, the only thing special being the way that you format these fields.

    After realizing this, the solution I eventually arrived at was to generate the few SOAP requests (think it was two) I needed using a desktop SOAP tool like SoapUI and then simply send these generated requests using a non-SOAP 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.