Reputation: 151
I'm using this library in node.js to make SOAP API calls: https://github.com/vpulim/node-soap
Here are the wsdl and xsd files for reference: https://drive.google.com/open?id=1ha7CqyJBnkISsI0wafwVrV4qG813ML64
These calls are being made to Cisco CUCM (VOIP application server). To give context, all it's trying to do is get the details for a specific phone with getPhone method, with device name SEPAAAABBBBCCCC in this example. Here is the code:
var soap = require("soap");
var url = "AXLAPI.wsdl";
var auth = "Basic " + new Buffer("axl" + ":" + "cisco").toString("base64");
var args = {
name: "SEPAAAABBBBCCCC"
};
soap.createClient(url, function(err, client) {
client.setEndpoint("https://192.168.138.15:8443/axl");
client.addHttpHeader("Authorization", auth);
client.setSecurity(new soap.ClientSSLSecurity(undefined,undefined, undefined, {rejectUnauthorized: false,},));
client.getPhone(args, function(err,result) {
if (err) {
console.log("soap api error is: " + err);
console.log("last request: " + client.lastRequest);
process.exit(1);
}
console.log("result is: " + result);
});
if (err) {
console.log("soap client error is: " + err);
}
});
It's not working. The error that is printed to the console log is not very useful. It simply states: "Error: Cannot parse response."
The library has function where you can log the XML request (client.lastRequest in the code). This is the output I get:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:s0="http://www.cisco.com/AXLAPIService/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:xsd1="http://www.cisco.com/AXL/API/11.5">
<soap:Header></soap:Header>
<soap:Body>
<getPhoneIn>
<name>SEPAAAABBBBCCCC</name>
</getPhoneIn>
</soap:Body>
</soap:Envelope>
But this is not correct. If I use postman to manually send an AXL request with the above body I get this fault string:
<faultstring>error: The document is not a getPhone@http://www.cisco.com/AXL/API/11.5: document element mismatch got getPhoneIn</faultstring>
I'm not sure how the library is getting a getPhoneIn element as it's not valid per the WSDL file. It should be getPhone.
EDIT: I'm posting the solution I used so it can help others (thanks to the excellent support and input from Terry)
"use-strict";
var soap = require("strong-soap").soap;
var request = require("request");
var url = "AXLAPI.wsdl";
var auth = "Basic " + new Buffer("axl" + ":" + "cisco").toString("base64");
var requestArgs = {
name: "SEPAAAABBBBCCCC"
};
var specialRequest = request.defaults({ strictSSL: false });
var options = {
endpoint: "https://192.168.138.15:8443/axl/",
request: specialRequest
};
soap.createClient(url, options, function(err, client) {
client.addHttpHeader("Authorization", auth);
var method = client.getPhone;
method(requestArgs, function (err, result, envelope, soapHeader) {
console.log("Result: " + JSON.stringify(result));
});
});
Upvotes: 2
Views: 2048
Reputation: 30675
I'm not sure how much this helps you, but I tested this with the strong-soap library, you get the following envelope:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header/>
<soap:Body>
<ns1:getPhone xmlns:ns1="http://www.cisco.com/AXL/API/11.5">
<name>test_name</name>
</ns1:getPhone>
</soap:Body>
</soap:Envelope>
Code is below:
"use strict";
var soap = require('strong-soap').soap;
var request = require("request");
// wsdl of the web service this client is going to invoke. For local wsdl you can use, url = './wsdls/stockquote.wsdl'
var url = './AXLAPI.wsdl';
// Use this to intercept calls from strong-soap if we want to fiddle with anything..
var stubRequest = (requestOptions, callbackFn) => {
console.log("Strong-Soap-Call-To-Request: ", requestOptions, callbackFn);
// Here you can change the HTTP method.. but don't do this if it's pulling the WSDL
if ((requestOptions.uri.search || "").toLowerCase() !== "?wsdl") {
console.log("Strong-Soap-Call-To-Request: Changing HTTP method");
requestOptions.method = 'POST';
}
console.log("Strong-Soap-Call-To-Request-After-Mods: ", requestOptions, callbackFn);
request(requestOptions, callbackFn);
};
var options = { endpoint: 'put service url here', request: stubRequest};
var requestArgs = { name: 'test_name' };
soap.createClient(url, options, function(err, client) {
var method = client.getPhone;
method(requestArgs, function(err, result, envelope, soapHeader) {
//response envelope
console.log('Response Envelope: \n' + envelope);
//'result' is the response body
console.log('Result: \n' + JSON.stringify(result));
});
});
You'd need to set the endpoint in the options object. Also the auth header will be required.
The describe method is also useful:
// Describes the entire WSDL in a JSON tree object form.
var description = client.describe();
Upvotes: 1