diff --git a/package-lock.json b/package-lock.json index 9f667a9b..a58d640d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { - "name": "strong-soap", - "version": "3.4.2", + "name": "strong-soap-without-parser", + "version": "2.0.6", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index 04579d1b..fceb0beb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "strong-soap", - "version": "3.4.2", + "name": "strong-soap-without-parser", + "version": "2.0.6", "description": "A minimal node SOAP client", "engines": { "node": ">=8.11.1" diff --git a/src/client.js b/src/client.js index 0652ae76..94babb2a 100644 --- a/src/client.js +++ b/src/client.js @@ -3,23 +3,23 @@ // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT -'use strict'; - -var g = require('./globalize'); -var HttpClient = require('./http'), - assert = require('assert'), - xmlBuilder = require('xmlbuilder'), - XMLHandler = require('./parser/xmlHandler'), - NamespaceContext = require('./parser/nscontext'), - Operation = require('./parser/wsdl/operation'), - SOAPElement = require('./soapModel').SOAPElement, - Base = require('./base'), - util = require('util'), - _ = require('lodash'), - debug = require('debug')('strong-soap:client'), - debugDetail = require('debug')('strong-soap:client:detail'), - debugSensitive = require('debug')('strong-soap:client:sensitive'), - utils = require('./utils'); +"use strict"; + +var g = require("./globalize"); +var HttpClient = require("./http"), + assert = require("assert"), + xmlBuilder = require("xmlbuilder"), + XMLHandler = require("./parser/xmlHandler"), + NamespaceContext = require("./parser/nscontext"), + Operation = require("./parser/wsdl/operation"), + SOAPElement = require("./soapModel").SOAPElement, + Base = require("./base"), + util = require("util"), + _ = require("lodash"), + debug = require("debug")("strong-soap:client"), + debugDetail = require("debug")("strong-soap:client:detail"), + debugSensitive = require("debug")("strong-soap:client:sensitive"), + utils = require("./utils"); class Client extends Base { constructor(wsdl, endpoint, options) { @@ -59,8 +59,10 @@ class Client extends Base { var ports = service.ports; var def = {}; for (var name in ports) { - def[name] = this._definePort(ports[name], - endpoint ? endpoint : ports[name].location); + def[name] = this._definePort( + ports[name], + endpoint ? endpoint : ports[name].location + ); } return def; } @@ -80,21 +82,21 @@ class Client extends Base { _defineOperation(operation, location) { var self = this; var temp; - return function(args, callback, options, extraHeaders) { + return function (args, callback, options, extraHeaders) { if (!args) args = {}; - if (typeof args === 'function') { + if (typeof args === "function") { callback = args; args = {}; - } else if (typeof options === 'function') { + } else if (typeof options === "function") { temp = callback; callback = options; options = temp; - } else if (typeof extraHeaders === 'function') { + } else if (typeof extraHeaders === "function") { temp = callback; callback = extraHeaders; extraHeaders = options; options = temp; - } else if (typeof callback === 'object') { + } else if (typeof callback === "object") { extraHeaders = options; options = callback; callback = undefined; @@ -105,8 +107,6 @@ class Client extends Base { }; } - - _invoke(operation, args, location, callback, options, extraHeaders) { var self = this, name = operation.$name, @@ -115,52 +115,66 @@ class Client extends Base { style = operation.style, defs = this.wsdl.definitions, ns = defs.$targetNamespace, - encoding = '', - message = '', + encoding = "", + message = "", xml = null, req = null, soapAction, headers = { - 'Content-Type': 'text/xml; charset=utf-8' + "Content-Type": "text/xml; charset=utf-8", }, - dynamicSoapHeaderProperty = ['soapHeaders'], + dynamicSoapHeaderProperty = ["soapHeaders"], dynamicSoapHeaders = {}; - debug('client request. operation: %s args: %j options: %j extraHeaders: %j', operation.name, args, options, extraHeaders); + debug( + "client request. operation: %s args: %j options: %j extraHeaders: %j", + operation.name, + args, + options, + extraHeaders + ); - var soapNsURI = 'http://schemas.xmlsoap.org/soap/envelope/'; - var soapNsPrefix = this.wsdl.options.envelopeKey || 'soap'; + var soapNsURI = "http://schemas.xmlsoap.org/soap/envelope/"; + var soapNsPrefix = this.wsdl.options.envelopeKey || "soap"; - var soapVersion = this.wsdl.options.forceSoapVersion || operation.soapVersion; + var soapVersion = + this.wsdl.options.forceSoapVersion || operation.soapVersion; - if (soapVersion === '1.2') { - headers['Content-Type'] = 'application/soap+xml; charset=utf-8'; - soapNsURI = 'http://www.w3.org/2003/05/soap-envelope'; + if (soapVersion === "1.2") { + headers["Content-Type"] = "application/soap+xml; charset=utf-8"; + soapNsURI = "http://www.w3.org/2003/05/soap-envelope"; } - debug('client request. soapNsURI: %s soapNsPrefix: %s ', soapNsURI, soapNsPrefix); + debug( + "client request. soapNsURI: %s soapNsPrefix: %s ", + soapNsURI, + soapNsPrefix + ); if (this.SOAPAction) { soapAction = this.SOAPAction; } else if (operation.soapAction != null) { soapAction = operation.soapAction; } else { - soapAction = ((ns.lastIndexOf("/") !== ns.length - 1) ? ns + "/" : ns) + name; + soapAction = + (ns.lastIndexOf("/") !== ns.length - 1 ? ns + "/" : ns) + name; } - if (soapVersion !== '1.2' || operation.soapActionRequired) { + if (soapVersion !== "1.2" || operation.soapActionRequired) { headers.SOAPAction = '"' + soapAction + '"'; } - debug('client request. soapAction: %s', soapAction); + debug("client request. soapAction: %s", soapAction); options = options || {}; - debugSensitive('client request. options: %j', options); + debugSensitive("client request. options: %j", options); - dynamicSoapHeaders = _.merge(_.pick(extraHeaders, dynamicSoapHeaderProperty), - _.pick(options, dynamicSoapHeaderProperty)); + dynamicSoapHeaders = _.merge( + _.pick(extraHeaders, dynamicSoapHeaderProperty), + _.pick(options, dynamicSoapHeaderProperty) + ); - debug('Soap xml payload extra headers: %j', dynamicSoapHeaders); + debug("Soap xml payload extra headers: %j", dynamicSoapHeaders); extraHeaders = _.omit(extraHeaders, dynamicSoapHeaderProperty); options = _.omit(options, dynamicSoapHeaderProperty); @@ -174,14 +188,14 @@ class Client extends Base { } // Clear and Add new SOAP Headers - if (!_.isEmpty(dynamicSoapHeaders)) { - this.clearSoapHeaders(); - for (var attr in dynamicSoapHeaders) { - this.addSoapHeader(dynamicSoapHeaders[attr]); - } + if (!_.isEmpty(dynamicSoapHeaders)) { + this.clearSoapHeaders(); + for (var attr in dynamicSoapHeaders) { + this.addSoapHeader(dynamicSoapHeaders[attr]); + } } - - debug('client request. headers: %j', headers); + + debug("client request. headers: %j", headers); //Unlike other security objects, NTLMSecurity is passed in through client options rather than client.setSecurity(ntlmSecurity) as some //remote wsdl retrieval needs NTLM authentication before client object gets created. Hence, set NTLMSecurity instance to the client object @@ -193,17 +207,16 @@ class Client extends Base { // Allow the security object to add headers if (self.security && self.security.addHttpHeaders) { self.security.addHttpHeaders(headers); - debugSensitive('client request. options: %j', options); + debugSensitive("client request. options: %j", options); } if (self.security && self.security.addOptions) { self.security.addOptions(options); - debugSensitive('client request. options: %j', options); + debugSensitive("client request. options: %j", options); } - - var nsContext = this.createNamespaceContext(soapNsPrefix, soapNsURI); - var xmlHandler = this.xmlHandler || new XMLHandler(this.wsdl.schemas, options); + var xmlHandler = + this.xmlHandler || new XMLHandler(this.wsdl.schemas, options); var envelope = Client.createSOAPEnvelope(soapNsPrefix, soapNsURI); var soapHeaderElement = envelope.header; @@ -217,19 +230,18 @@ class Client extends Base { let schemas = defs.schemas; - - for(let uri in schemas) { + for (let uri in schemas) { let complexTypes = schemas[uri].complexTypes; - if(complexTypes) { + if (complexTypes) { for (let type in complexTypes) { - complexTypes[type].describe(this.wsdl.definitions); + complexTypes[type].describe(this.wsdl.definitions); } } } - for(let uri in schemas) { + for (let uri in schemas) { let complexTypes = schemas[uri].complexTypes; - if(complexTypes) { + if (complexTypes) { for (let type in complexTypes) { complexTypes[type].describeChildren(this.wsdl.definitions); } @@ -237,15 +249,14 @@ class Client extends Base { } var operationDescriptor = operation.describe(this.wsdl.definitions); - debugDetail('client request. operationDescriptor: %j', operationDescriptor); + debugDetail("client request. operationDescriptor: %j", operationDescriptor); var inputBodyDescriptor = operationDescriptor.input.body; - debug('client request. inputBodyDescriptor: %j', inputBodyDescriptor); + debug("client request. inputBodyDescriptor: %j", inputBodyDescriptor); var inputHeadersDescriptor = operationDescriptor.input.headers; - - debug('client request, calling jsonToXml. args: %j', args); + debug("client request, calling jsonToXml. args: %j", args); xmlHandler.jsonToXml(soapBodyElement, nsContext, inputBodyDescriptor, args); if (self.security && self.security.postProcess) { @@ -255,119 +266,146 @@ class Client extends Base { //Bydefault pretty print is true and request envelope is created with newlines and indentations var prettyPrint = true; //some web services don't accept request envelope with newlines and indentations in which case user has to set {prettyPrint: false} as client option - if (self.httpClient.options && self.httpClient.options.prettyPrint !== undefined) { + if ( + self.httpClient.options && + self.httpClient.options.prettyPrint !== undefined + ) { prettyPrint = self.httpClient.options.prettyPrint; } - message = envelope.body.toString({pretty: prettyPrint}); - xml = envelope.doc.end({pretty: prettyPrint}); + message = envelope.body.toString({ pretty: prettyPrint }); + xml = envelope.doc.end({ pretty: prettyPrint }); - debug('Request envelope: %s', xml); + debug("Request envelope: %s", xml); self.lastMessage = message; self.lastRequest = xml; self.lastEndpoint = location; - self.emit('message', message); - self.emit('request', xml); + self.emit("message", message); + self.emit("request", xml); - var tryJSONparse = function(body) { + var tryJSONparse = function (body) { try { return JSON.parse(body); - } - catch (err) { + } catch (err) { return undefined; } }; - req = self.httpClient.request(location, xml, function(err, response, body) { - var result; - var obj; - self.lastResponse = body; - self.lastResponseHeaders = response && response.headers; - self.lastElapsedTime = response && response.elapsedTime; - self.emit('response', body, response); - - debug('client response. response: %j body: %j', response, body); - - if (err) { - callback(err); - } else { - - //figure out if this is a Fault response or normal output from the server. - //There seem to be no good way to figure this out other than - //checking for element in server response. - if (body.indexOf('') > -1 || body.indexOf('') > -1) { - var outputEnvDescriptor = operationDescriptor.faultEnvelope; - } else { - var outputEnvDescriptor = operationDescriptor.outputEnvelope; - } - try { - debugDetail('client response. outputEnvDescriptor: %j', outputEnvDescriptor); - obj = xmlHandler.xmlToJson(nsContext, body, outputEnvDescriptor); - } catch (error) { - // When the output element cannot be looked up in the wsdl and the body is JSON - // instead of sending the error, we pass the body in the response. - debug('client response. error message: %s', error.message); - - if (!output) { - debug('client response. output not present'); - // If the response is JSON then return it as-is. - var json = _.isObject(body) ? body : tryJSONparse(body); - if (json) { - return callback(null, response, json); + req = self.httpClient.request( + location, + xml, + function (err, response, body) { + var result; + var obj; + self.lastResponse = body; + self.lastResponseHeaders = response && response.headers; + self.lastElapsedTime = response && response.elapsedTime; + self.emit("response", body, response); + + debug("client response. response: %j body: %j", response, body); + + if (err) { + callback(err); + } else { + //figure out if this is a Fault response or normal output from the server. + //There seem to be no good way to figure this out other than + //checking for element in server response. + if ( + body.indexOf("") > -1 || + body.indexOf("") > -1 + ) { + var outputEnvDescriptor = operationDescriptor.faultEnvelope; + } else { + var outputEnvDescriptor = operationDescriptor.outputEnvelope; + } + try { + debugDetail( + "client response. outputEnvDescriptor: %j", + outputEnvDescriptor + ); + obj = xmlHandler.xmlToJson(nsContext, body, outputEnvDescriptor); + } catch (error) { + // When the output element cannot be looked up in the wsdl and the body is JSON + // instead of sending the error, we pass the body in the response. + debug("client response. error message: %s", error.message); + + if (!output) { + debug("client response. output not present"); + // If the response is JSON then return it as-is. + var json = _.isObject(body) ? body : tryJSONparse(body); + if (json) { + return callback(null, response, json); + } } + //Reaches here for Fault processing as well since Fault is thrown as an error in xmlHandler.xmlToJson(..) function. + error.response = response; + error.body = body; + self.emit("soapError", error); + return callback(error, response, body); } - //Reaches here for Fault processing as well since Fault is thrown as an error in xmlHandler.xmlToJson(..) function. - error.response = response; - error.body = body; - self.emit('soapError', error); - return callback(error, response, body); - } - if (!output) { - // one-way, no output expected - return callback(null, null, body, obj.Header); - } - if (typeof obj.Body !== 'object') { - var error = new Error(g.f('Cannot parse response')); - error.response = response; - error.body = body; - return callback(error, obj, body); - } + if (!output) { + // one-way, no output expected + return callback(null, null, body, obj.Header); + } + if (typeof obj.Body !== "object") { + var error = new Error(g.f("Cannot parse response")); + error.response = response; + error.body = body; + return callback(error, obj, body); + } - var outputBodyDescriptor = operationDescriptor.output.body; - var outputHeadersDescriptor = operationDescriptor.output.headers; + var outputBodyDescriptor = operationDescriptor.output.body; + var outputHeadersDescriptor = operationDescriptor.output.headers; - if (outputBodyDescriptor.elements.length) { - result = obj.Body[outputBodyDescriptor.elements[0].qname.name]; - } - // RPC/literal response body may contain elements with added suffixes I.E. - // 'Response', or 'Output', or 'Out' - // This doesn't necessarily equal the ouput message name. See WSDL 1.1 Section 2.4.5 - if (!result) { - var outputName = output.$name && - output.$name.replace(/(?:Out(?:put)?|Response)$/, ''); - result = obj.Body[outputName]; - } - if (!result) { - ['Response', 'Out', 'Output', '.Response', '.Out', '.Output'].forEach(function(term) { - if (obj.Body.hasOwnProperty(name + term)) { - return result = obj.Body[name + term]; - } - }); + if (outputBodyDescriptor.elements.length) { + result = obj.Body; + } + // RPC/literal response body may contain elements with added suffixes I.E. + // 'Response', or 'Output', or 'Out' + // This doesn't necessarily equal the ouput message name. See WSDL 1.1 Section 2.4.5 + if (!result) { + var outputName = + output.$name && + output.$name.replace(/(?:Out(?:put)?|Response)$/, ""); + result = obj.Body[outputName]; + } + if (!result) { + [ + "Response", + "Out", + "Output", + ".Response", + ".Out", + ".Output", + ].forEach(function (term) { + if (obj.Body.hasOwnProperty(name + term)) { + return (result = obj.Body[name + term]); + } + }); + } + debug( + "client response. result: %j body: %j obj.Header: %j", + result, + body, + obj.Header + ); + + callback(null, result, body, obj.Header); } - debug('client response. result: %j body: %j obj.Header: %j', result, body, obj.Header); - - callback(null, result, body, obj.Header); - } - }, headers, options, self); + }, + headers, + options, + self + ); // Added mostly for testability, but possibly useful for debugging if (req != null) { self.lastRequestHeaders = req.headers; } - debug('client response. lastRequestHeaders: %j', self.lastRequestHeaders); + debug("client response. lastRequestHeaders: %j", self.lastRequestHeaders); } } diff --git a/src/parser/wsdl/binding.js b/src/parser/wsdl/binding.js index 935c82da..32c3069d 100644 --- a/src/parser/wsdl/binding.js +++ b/src/parser/wsdl/binding.js @@ -3,21 +3,21 @@ // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT -'use strict'; +"use strict"; -var WSDLElement = require('./wsdlElement'); -var QName = require('../qname'); +var WSDLElement = require("./wsdlElement"); +var QName = require("../qname"); class Binding extends WSDLElement { constructor(nsName, attrs, options) { super(nsName, attrs, options); - this.transport = ''; - this.style = ''; + this.transport = ""; + this.style = ""; } addChild(child) { // soap:binding - if (child.name === 'binding') { + if (child.name === "binding") { this.transport = child.$transport; this.style = child.$style; } @@ -35,9 +35,8 @@ class Binding extends WSDLElement { portType.postProcess(definitions); this.portType = portType; - for (var i = 0, child; child = children[i]; i++) { - if (child.name !== 'operation') - continue; + for (var i = 0, child; (child = children[i]); i++) { + if (child.name !== "operation") continue; var operation = this.portType.operations[child.$name]; if (operation) { this.operations[child.$name] = child; @@ -62,7 +61,7 @@ class Binding extends WSDLElement { // For RPC style child.parameterOrder = operation.$parameterOrder.split(/\s+/); } - child.style = child.style || style; + child.style = child.style || style || "document"; child.postProcess(definitions); } } @@ -74,17 +73,21 @@ class Binding extends WSDLElement { describe(definitions) { if (this.descriptor) return this.descriptor; - var operations = this.descriptor = {}; + var operations = (this.descriptor = {}); for (var name in this.operations) { var operation = this.operations[name]; operations[name] = operation.describe(definitions); } return operations; - }; + } } -Binding.elementName = 'binding'; -Binding.allowedChildren = ['binding', 'SecuritySpec', 'operation', - 'documentation']; +Binding.elementName = "binding"; +Binding.allowedChildren = [ + "binding", + "SecuritySpec", + "operation", + "documentation", +]; module.exports = Binding; diff --git a/src/parser/wsdl/operation.js b/src/parser/wsdl/operation.js index 0a5796eb..31cabf10 100644 --- a/src/parser/wsdl/operation.js +++ b/src/parser/wsdl/operation.js @@ -3,25 +3,25 @@ // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT -'use strict'; +"use strict"; -var g = require('../../globalize'); -var WSDLElement = require('./wsdlElement'); -var descriptor = require('../xsd/descriptor'); +var g = require("../../globalize"); +var WSDLElement = require("./wsdlElement"); +var descriptor = require("../xsd/descriptor"); var ElementDescriptor = descriptor.ElementDescriptor; var TypeDescriptor = descriptor.TypeDescriptor; -var QName = require('../qname'); -var helper = require('../helper'); -var SimpleType = require('../xsd/simpleType'); +var QName = require("../qname"); +var helper = require("../helper"); +var SimpleType = require("../xsd/simpleType"); -var assert = require('assert'); +var assert = require("assert"); const Style = { - documentLiteralWrapped: 'documentLiteralWrapped', - documentLiteral: 'documentLiteral', - rpcLiteral: 'rpcLiteral', - rpcEncoded: 'rpcEncoded', - documentEncoded: 'documentEncoded' + documentLiteralWrapped: "documentLiteralWrapped", + documentLiteral: "documentLiteral", + rpcLiteral: "rpcLiteral", + rpcEncoded: "rpcEncoded", + documentEncoded: "documentEncoded", }; class Operation extends WSDLElement { @@ -35,26 +35,29 @@ class Operation extends WSDLElement { addChild(child) { switch (child.name) { - case 'input': + case "input": this.input = child; break; - case 'output': + case "output": this.output = child; break; - case 'fault': + case "fault": this.faults.push(child); break; - case 'operation': // soap:operation - this.soapAction = child.$soapAction || ''; - this.style = child.$style || ''; - this.soapActionRequired = child.$soapActionRequired === 'true' || child.$soapActionRequired === '1' || false; + case "operation": // soap:operation + this.soapAction = child.$soapAction || ""; + this.style = child.$style || ""; + this.soapActionRequired = + child.$soapActionRequired === "true" || + child.$soapActionRequired === "1" || + false; //figure out from the binding operation soap version 1.1 or 1.2 - if (child.nsURI === 'http://schemas.xmlsoap.org/wsdl/soap/') { - this.soapVersion ='1.1'; - } else if(child.nsURI === 'http://schemas.xmlsoap.org/wsdl/soap12/') { - this.soapVersion ='1.2'; + if (child.nsURI === "http://schemas.xmlsoap.org/wsdl/soap/") { + this.soapVersion = "1.1"; + } else if (child.nsURI === "http://schemas.xmlsoap.org/wsdl/soap12/") { + this.soapVersion = "1.2"; } else { - this.soapVersion = '1.1'; + this.soapVersion = "1.1"; } break; } @@ -68,7 +71,7 @@ class Operation extends WSDLElement { for (let i = 0, n = this.faults.length; i < n; i++) { this.faults[i].postProcess(definitions); } - if (this.parent.name === 'binding') { + if (this.parent.name === "binding") { this.getMode(); } this._processed = true; @@ -81,14 +84,17 @@ class Operation extends WSDLElement { if (param == null) return null; var headers = new descriptor.TypeDescriptor(); if (!param.headers) return headers; - param.headers.forEach(function(header) { + param.headers.forEach(function (header) { var part = header.part; if (part && part.element) { headers.addElement(part.element.describe(definitions)); } else if (part && part.type) { - g.warn('{{WS-I}} violation: ' + - '{{http://ws-i.org/profiles/basicprofile-1.2-2010-11-09.html#BP2113}}' + - ' part %s', part.$name); + g.warn( + "{{WS-I}} violation: " + + "{{http://ws-i.org/profiles/basicprofile-1.2-2010-11-09.html#BP2113}}" + + " part %s", + part.$name + ); } }); return headers; @@ -102,9 +108,12 @@ class Operation extends WSDLElement { if (part && part.element) { faults[f] = part.element.describe(definitions); } else { - g.warn('{{WS-I}} violation: ' + - '{{http://ws-i.org/profiles/basicprofile-1.2-2010-11-09.html#BP2113}}' + - ' part %s', part.$name); + g.warn( + "{{WS-I}} violation: " + + "{{http://ws-i.org/profiles/basicprofile-1.2-2010-11-09.html#BP2113}}" + + " part %s", + part.$name + ); } } return faults; @@ -157,12 +166,21 @@ class Operation extends WSDLElement { case Style.rpcLiteral: case Style.rpcEncoded: // The operation wrapper element - let nsURI = (this.input && this.input.body && - this.input.body.namespace) || this.targetNamespace; + let nsURI = + (this.input && this.input.body && this.input.body.namespace) || + this.targetNamespace; input = new descriptor.ElementDescriptor( - new QName(nsURI, this.$name), null, 'qualified', false); + new QName(nsURI, this.$name), + null, + "qualified", + false + ); output = new descriptor.ElementDescriptor( - new QName(nsURI, this.$name + 'Response'), null, 'qualified', false); + new QName(nsURI, this.$name + "Response"), + null, + "qualified", + false + ); let inputParts = new descriptor.TypeDescriptor(); let outputParts = new descriptor.TypeDescriptor(); if (this.input && this.input.body) { @@ -171,13 +189,21 @@ class Operation extends WSDLElement { let type; if (part.type) { if (part.type instanceof SimpleType) { - var qName = new QName(part.type.targetNamespace, part.type.$name, part.type.prefix); + var qName = new QName( + part.type.targetNamespace, + part.type.$name, + part.type.prefix + ); type = qName; } else { type = part.type.qname; } let element = new descriptor.ElementDescriptor( - new QName(nsURI, p), type, 'unqualified', false); + new QName(nsURI, p), + type, + "unqualified", + false + ); inputParts.addElement(element); } else if (part.element) { var elementDescriptor = part.element.describe(definitions); @@ -191,13 +217,21 @@ class Operation extends WSDLElement { let type; if (part.type) { if (part.type instanceof SimpleType) { - var qName = new QName(part.type.targetNamespace, part.type.$name, part.type.prefix); + var qName = new QName( + part.type.targetNamespace, + part.type.$name, + part.type.prefix + ); type = qName; } else { type = part.type.qname; } let element = new descriptor.ElementDescriptor( - new QName(nsURI, p), type, 'unqualified', false); + new QName(nsURI, p), + type, + "unqualified", + false + ); outputParts.addElement(element); } else if (part.element) { let elementDescriptor = part.element.describe(definitions); @@ -209,7 +243,9 @@ class Operation extends WSDLElement { output.elements = outputParts.elements; break; case Style.documentEncoded: - throw new Error(g.f('{{WSDL}} style not supported: %s', Style.documentEncoded)); + throw new Error( + g.f("{{WSDL}} style not supported: %s", Style.documentEncoded) + ); } let faults = this.describeFaults(definitions); @@ -223,54 +259,85 @@ class Operation extends WSDLElement { soapVersion: this.soapVersion, input: { body: input, - headers: inputHeaders + headers: inputHeaders, }, output: { body: output, - headers: outputHeaders + headers: outputHeaders, }, faults: { - body: {Fault : {faults}} - } + body: { Fault: { faults } }, + }, }; - this.descriptor.inputEnvelope = - Operation.createEnvelopeDescriptor(this.descriptor.input, false, this.soapVersion); - this.descriptor.outputEnvelope = - Operation.createEnvelopeDescriptor(this.descriptor.output, true, this.soapVersion); - this.descriptor.faultEnvelope = - Operation.createEnvelopeDescriptor(this.descriptor.faults, true, this.soapVersion); + this.descriptor.inputEnvelope = Operation.createEnvelopeDescriptor( + this.descriptor.input, + false, + this.soapVersion + ); + this.descriptor.outputEnvelope = Operation.createEnvelopeDescriptor( + this.descriptor.output, + true, + this.soapVersion + ); + this.descriptor.faultEnvelope = Operation.createEnvelopeDescriptor( + this.descriptor.faults, + true, + this.soapVersion + ); return this.descriptor; } - static createEnvelopeDescriptor(parameterDescriptor, isOutput, soapVersion, prefix, nsURI) { - prefix = prefix || 'soap'; + static createEnvelopeDescriptor( + parameterDescriptor, + isOutput, + soapVersion, + prefix, + nsURI + ) { + prefix = prefix || "soap"; var soapNsURI; - if (soapVersion === '1.1') { - soapNsURI = 'http://schemas.xmlsoap.org/soap/envelope/'; - } else if (soapVersion === '1.2') { - soapNsURI = 'http://www.w3.org/2003/05/soap-envelope'; + if (soapVersion === "1.1") { + soapNsURI = "http://schemas.xmlsoap.org/soap/envelope/"; + } else if (soapVersion === "1.2") { + soapNsURI = "http://www.w3.org/2003/05/soap-envelope"; } nsURI = nsURI || soapNsURI; var descriptor = new TypeDescriptor(); var envelopeDescriptor = new ElementDescriptor( - new QName(nsURI, 'Envelope', prefix), null, 'qualified', false); + new QName(nsURI, "Envelope", prefix), + null, + "qualified", + false + ); descriptor.add(envelopeDescriptor); var headerDescriptor = new ElementDescriptor( - new QName(nsURI, 'Header', prefix), null, 'qualified', false); + new QName(nsURI, "Header", prefix), + null, + "qualified", + false + ); var bodyDescriptor = new ElementDescriptor( - new QName(nsURI, 'Body', prefix), null, 'qualified', false); + new QName(nsURI, "Body", prefix), + null, + "qualified", + false + ); envelopeDescriptor.addElement(headerDescriptor); envelopeDescriptor.addElement(bodyDescriptor); //add only if input or output. Fault is list of faults unlike input/output element and fault needs further processing below, //before it can be added to the - if (parameterDescriptor && parameterDescriptor.body && !parameterDescriptor.body.Fault) { + if ( + parameterDescriptor && + parameterDescriptor.body && + !parameterDescriptor.body?.Fault + ) { bodyDescriptor.add(parameterDescriptor.body); } @@ -293,48 +360,113 @@ class Operation extends WSDLElement { */ - if (isOutput && parameterDescriptor && parameterDescriptor.body.Fault) { - let xsdStr = new QName(helper.namespaces.xsd, 'string', 'xsd'); + if (isOutput && parameterDescriptor && parameterDescriptor.body?.Fault) { + let xsdStr = new QName(helper.namespaces.xsd, "string", "xsd"); var form; - if (soapVersion === '1.1') { - form = 'unqualified'; - } else if (soapVersion === '1.2') { - form = 'qualified'; + if (soapVersion === "1.1") { + form = "unqualified"; + } else if (soapVersion === "1.2") { + form = "qualified"; } let faultDescriptor = new ElementDescriptor( - new QName(nsURI, 'Fault', prefix), null, 'qualified', false); + new QName(nsURI, "Fault", prefix), + null, + "qualified", + false + ); bodyDescriptor.add(faultDescriptor); let detailDescriptor; - if (soapVersion === '1.1') { + if (soapVersion === "1.1") { faultDescriptor.add( - new ElementDescriptor(new QName(nsURI, 'faultcode', prefix), null, form, false)); + new ElementDescriptor( + new QName(nsURI, "faultcode", prefix), + null, + form, + false + ) + ); faultDescriptor.add( - new ElementDescriptor(new QName(nsURI, 'faultstring', prefix), null, form, false)); + new ElementDescriptor( + new QName(nsURI, "faultstring", prefix), + null, + form, + false + ) + ); faultDescriptor.add( - new ElementDescriptor(new QName(nsURI, 'faultactor', prefix), null, form, false)); - detailDescriptor = - new ElementDescriptor(new QName(nsURI, 'detail', prefix), null, form, false); + new ElementDescriptor( + new QName(nsURI, "faultactor", prefix), + null, + form, + false + ) + ); + detailDescriptor = new ElementDescriptor( + new QName(nsURI, "detail", prefix), + null, + form, + false + ); faultDescriptor.add(detailDescriptor); - } else if (soapVersion === '1.2') { - let code = new ElementDescriptor(new QName(nsURI, 'Code', prefix)); + } else if (soapVersion === "1.2") { + let code = new ElementDescriptor(new QName(nsURI, "Code", prefix)); code.add( - new ElementDescriptor(new QName(nsURI, 'Value', prefix), null, form, false)); - let subCode = new ElementDescriptor(new QName(nsURI, 'Subcode', prefix), null, form, false); - code.add (subCode); + new ElementDescriptor( + new QName(nsURI, "Value", prefix), + null, + form, + false + ) + ); + let subCode = new ElementDescriptor( + new QName(nsURI, "Subcode", prefix), + null, + form, + false + ); + code.add(subCode); subCode.add( - new ElementDescriptor(new QName(nsURI, 'Value', prefix), null, form, false)); + new ElementDescriptor( + new QName(nsURI, "Value", prefix), + null, + form, + false + ) + ); faultDescriptor.add(code, null, form, false); - let reason = new ElementDescriptor(new QName(nsURI, 'Reason', prefix)); + let reason = new ElementDescriptor(new QName(nsURI, "Reason", prefix)); reason.add( - new ElementDescriptor(new QName(nsURI, 'Text', prefix), null, form, false)); + new ElementDescriptor( + new QName(nsURI, "Text", prefix), + null, + form, + false + ) + ); faultDescriptor.add(reason, null, form, false); faultDescriptor.add( - new ElementDescriptor(new QName(nsURI, 'Node', prefix), null, form, false)); + new ElementDescriptor( + new QName(nsURI, "Node", prefix), + null, + form, + false + ) + ); faultDescriptor.add( - new ElementDescriptor(new QName(nsURI, 'Role', prefix), null, form, false)); - detailDescriptor = - new ElementDescriptor(new QName(nsURI, 'Detail', prefix), null, form, false); + new ElementDescriptor( + new QName(nsURI, "Role", prefix), + null, + form, + false + ) + ); + detailDescriptor = new ElementDescriptor( + new QName(nsURI, "Detail", prefix), + null, + form, + false + ); faultDescriptor.add(detailDescriptor); } //multiple faults may be defined in wsdl for this operation. Go though every Fault and add it under element. @@ -347,8 +479,9 @@ class Operation extends WSDLElement { } getMode() { - let use = this.input && this.input.body && this.input.body.use || 'literal'; - if (this.style === 'document' && use === 'literal') { + let use = + (this.input && this.input.body && this.input.body.use) || "literal"; + if (this.style === "document" && use === "literal") { // document literal let element = null; let count = 0; @@ -357,8 +490,8 @@ class Operation extends WSDLElement { let part = this.input.body.parts[p]; element = part.element; if (!(part.element && !part.type)) { - console.error('Document/literal part should use element', part); - throw new Error('Document/literal part should use element'); + console.error("Document/literal part should use element", part); + throw new Error("Document/literal part should use element"); } count++; } @@ -371,8 +504,10 @@ class Operation extends WSDLElement { for (let p in this.output.body.parts) { let part = this.output.body.parts[p]; element = part.element; - assert(part.element && !part.type, - 'Document/literal part should use element'); + assert( + part.element && !part.type, + "Document/literal part should use element" + ); count++; } } @@ -384,22 +519,25 @@ class Operation extends WSDLElement { } else { this.mode = Style.documentLiteral; } - } else if (this.style === 'document' && use === 'encoded') { + } else if (this.style === "document" && use === "encoded") { this.mode = Style.documentEncoded; - } else if (this.style === 'rpc' && use === 'encoded') { + } else if (this.style === "rpc" && use === "encoded") { this.mode = Style.rpcEncoded; - } else if (this.style === 'rpc' && use === 'literal') { + } else if (this.style === "rpc" && use === "literal") { this.mode = Style.rpcLiteral; } return this.mode; } - } Operation.Style = Style; -Operation.elementName = 'operation'; -Operation.allowedChildren = ['documentation', 'input', 'output', 'fault', - 'operation']; +Operation.elementName = "operation"; +Operation.allowedChildren = [ + "documentation", + "input", + "output", + "fault", + "operation", +]; module.exports = Operation; - diff --git a/src/parser/xmlHandler.js b/src/parser/xmlHandler.js index 28c7895b..4b2e1039 100644 --- a/src/parser/xmlHandler.js +++ b/src/parser/xmlHandler.js @@ -3,37 +3,65 @@ // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT -'use strict'; - -var xmlBuilder = require('xmlbuilder'); -var sax = require('sax'); -var stream = require('stream'); -var assert = require('assert'); -var selectn = require('selectn'); -var debug = require('debug')('strong-soap:xmlhandler'); -var descriptor = require('./xsd/descriptor'); +"use strict"; + +var xmlBuilder = require("xmlbuilder"); +var sax = require("sax"); +var stream = require("stream"); +var assert = require("assert"); +var selectn = require("selectn"); +var debug = require("debug")("strong-soap:xmlhandler"); +var descriptor = require("./xsd/descriptor"); var ElementDescriptor = descriptor.ElementDescriptor; var AttributeDescriptor = descriptor.AttributeDescriptor; var TypeDescriptor = descriptor.TypeDescriptor; -var QName = require('./qname'); -var helper = require('./helper'); -var NamespaceContext = require('./nscontext'); - +var QName = require("./qname"); +var helper = require("./helper"); +var NamespaceContext = require("./nscontext"); class XMLHandler { constructor(schemas, options) { this.schemas = schemas || {}; this.options = options || {}; - this.options.valueKey = this.options.valueKey || '$value'; - this.options.xmlKey = this.options.xmlKey || '$xml'; - this.options.attributesKey = this.options.attributesKey || '$attributes'; - this.options.xsiTypeKey = this.options.xsiTypeKey || '$xsiType'; + this.options.valueKey = this.options.valueKey || "$value"; + this.options.xmlKey = this.options.xmlKey || "$xml"; + this.options.attributesKey = this.options.attributesKey || "$attributes"; + this.options.xsiTypeKey = this.options.xsiTypeKey || "$xsiType"; } jsonToXml(node, nsContext, descriptor, val) { + const parameterName = descriptor?.qname?.name; + const maintainTagsNames = [ + "CountryCode", + "ChannelCode", + "SystemCode", + "ClientCode", + "ClientGroupCode", + "CompanyCode", + "SchemeCode", + "ClientUserId", + "ChannelGroupCode", + "BusinessEventSourceCode", + "BusinessEventCode", + "Surname", + "Title", + "AddressLine1", + "AddressCategory", + "PostalCode", + ]; + if ( + (val === null || val === "") && + !maintainTagsNames.includes(parameterName) + ) { + return node; + } + if (node == null) { - node = xmlBuilder.begin( - {version: '1.0', encoding: 'UTF-8', standalone: true}); + node = xmlBuilder.begin({ + version: "1.0", + encoding: "UTF-8", + standalone: true, + }); } if (nsContext == null) { nsContext = new NamespaceContext(); @@ -44,13 +72,17 @@ class XMLHandler { if (descriptor instanceof AttributeDescriptor) { val = toXmlDateOrTime(descriptor, val); name = descriptor.qname.name; - if (descriptor.form === 'unqualified') { + if (descriptor.form === "unqualified") { node.attribute(name, val); } else if (descriptor.qname) { - let mapping = declareNamespace(nsContext, node, descriptor.qname.prefix, - descriptor.qname.nsURI); + let mapping = declareNamespace( + nsContext, + node, + descriptor.qname.prefix, + descriptor.qname.nsURI + ); let prefix = mapping ? mapping.prefix : descriptor.qname.prefix; - let attrName = prefix ? prefix + ':' + name : name; + let attrName = prefix ? prefix + ":" + name : name; node.attribute(attrName, val); } return node; @@ -68,20 +100,20 @@ class XMLHandler { return node; } } - if(val !== null && typeof val === "object"){ + if (val !== null && typeof val === "object") { // check for $attributes field - if (typeof val[this.options.attributesKey] !== "undefined"){ + if (typeof val[this.options.attributesKey] !== "undefined") { attrs = val[this.options.attributesKey]; } // add any $value field as xml element value - if (typeof val[this.options.valueKey] !== "undefined"){ + if (typeof val[this.options.valueKey] !== "undefined") { val = val[this.options.valueKey]; } } let element; let elementName; let xmlns; - if (descriptor.form === 'unqualified') { + if (descriptor.form === "unqualified") { elementName = name; nsContext.pushContext(); nameSpaceContextCreated = true; @@ -94,26 +126,34 @@ class XMLHandler { // if namespace not declared, declare it if (mapping === null || mapping.declared === false) { newlyDeclared = true; - mapping = declareNamespace(nsContext, null, - descriptor.qname.prefix, descriptor.qname.nsURI); + mapping = declareNamespace( + nsContext, + null, + descriptor.qname.prefix, + descriptor.qname.nsURI + ); } // add the element to a parent node let prefix = mapping ? mapping.prefix : descriptor.qname.prefix; - elementName = prefix ? prefix + ':' + name : name; + elementName = prefix ? prefix + ":" + name : name; // if namespace is newly declared add the xmlns attribute if (newlyDeclared) { - xmlns = prefix ? 'xmlns:' + prefix : 'xmlns'; + xmlns = prefix ? "xmlns:" + prefix : "xmlns"; } } // add the element to a parent node if (isSimple && /",""); + val = val.replace("", ""); element.cdata(val); - }else if(isSimple && typeof val !== "undefined" && val !== null - && typeof val[this.options.xmlKey] !== "undefined") { + } else if ( + isSimple && + typeof val !== "undefined" && + val !== null && + typeof val[this.options.xmlKey] !== "undefined" + ) { val = val[this.options.xmlKey]; element = node.element(elementName); val = toXmlDateOrTime(descriptor, val); @@ -138,11 +178,13 @@ class XMLHandler { } } val = toXmlDateOrTime(descriptor, val); - element = isSimple ? node.element(elementName, val) : node.element(elementName); + element = isSimple + ? node.element(elementName, val) + : node.element(elementName); } if (xmlns && descriptor.qname.nsURI) { - if (typeof element.attribute === 'function') { + if (typeof element.attribute === "function") { element.attribute(xmlns, descriptor.qname.nsURI); } } @@ -150,9 +192,9 @@ class XMLHandler { if (val == null) { if (descriptor.isNillable) { // Set xsi:nil = true - declareNamespace(nsContext, element, 'xsi', helper.namespaces.xsi); - if (typeof element.attribute === 'function') { - element.attribute('xsi:nil', true); + declareNamespace(nsContext, element, "xsi", helper.namespaces.xsi); + if (typeof element.attribute === "function") { + element.attribute("xsi:nil", true); } } } @@ -169,20 +211,24 @@ class XMLHandler { nsContext.popContext(); } return node; - } else if ( val != null) { - + } else if (val != null) { let attrs = val[this.options.attributesKey]; - if (typeof attrs === 'object') { + if (typeof attrs === "object") { for (let p in attrs) { let child = attrs[p]; if (p === this.options.xsiTypeKey) { if (descriptor instanceof ElementDescriptor) { if (descriptor.refOriginal) { if (descriptor.refOriginal.typeDescriptor) { - if (descriptor.refOriginal.typeDescriptor.inheritance){ - let extension = descriptor.refOriginal.typeDescriptor.inheritance[child.type]; + if (descriptor.refOriginal.typeDescriptor.inheritance) { + let extension = + descriptor.refOriginal.typeDescriptor.inheritance[ + child.type + ]; if (extension) { - descriptor.elements = descriptor.elements.concat(extension.elements); + descriptor.elements = descriptor.elements.concat( + extension.elements + ); } } } @@ -193,7 +239,7 @@ class XMLHandler { } } //val is not an object - simple or date types - if (val != null && ( typeof val !== 'object' || val instanceof Date)) { + if (val != null && (typeof val !== "object" || val instanceof Date)) { // for adding a field value nsContext.popContext() shouldnt be called val = toXmlDateOrTime(descriptor, val); element.text(val); @@ -215,7 +261,11 @@ class XMLHandler { return node; } - if (descriptor == null || descriptor === undefined || descriptor instanceof TypeDescriptor) { + if ( + descriptor == null || + descriptor === undefined || + descriptor instanceof TypeDescriptor + ) { this.mapObject(node, nsContext, descriptor, val); return node; } @@ -249,7 +299,8 @@ class XMLHandler { schema.simpleTypes[xsiType.name]; // The type might not be described // describe() takes wsdl definitions - xsiTypeDescriptor = xsiTypeInfo && xsiTypeInfo.describe({schemas: this.schemas}); + xsiTypeDescriptor = + xsiTypeInfo && xsiTypeInfo.describe({ schemas: this.schemas }); } break; } @@ -269,7 +320,7 @@ class XMLHandler { const keys = Object.keys(val); var names = [].concat(keys).sort((n1, n2) => { let result = compare(n1, n2, elementOrder); - if (result ===0) { + if (result === 0) { result = compare(n1, n2, keys); } return result; @@ -287,7 +338,7 @@ class XMLHandler { */ mapObject(node, nsContext, descriptor, val, attrs) { if (val == null) return node; - if (typeof val !== 'object' || (val instanceof Date)) { + if (typeof val !== "object" || val instanceof Date) { val = toXmlDateOrTime(descriptor, val); node.text(val); return node; @@ -297,7 +348,8 @@ class XMLHandler { var xsiType = this.getXsiType(descriptor, attrs); descriptor = xsiType || descriptor; - var elements = {}, attributes = {}; + var elements = {}, + attributes = {}; var elementOrder = []; if (descriptor != null) { for (let i = 0, n = descriptor.elements.length; i < n; i++) { @@ -320,21 +372,23 @@ class XMLHandler { if (!Array.isArray(val)) { const names = this._sortKeys(val, elementOrder); for (let p of names) { - if (p === this.options.attributesKey) - continue; - let child = val[p]; - let childDescriptor = elements[p] || attributes[p]; - if (childDescriptor == null) { - if (this.options.ignoreUnknownProperties) - continue; + if (p === this.options.attributesKey) continue; + let child = val[p]; + let childDescriptor = elements[p] || attributes[p]; + if (childDescriptor == null) { + if (this.options.ignoreUnknownProperties) continue; else childDescriptor = new ElementDescriptor( - QName.parse(p), null, 'unqualified', Array.isArray(child)); + QName.parse(p), + null, + "unqualified", + Array.isArray(child) + ); } if (childDescriptor) { this.jsonToXml(node, nsContext, childDescriptor, child); } - } + } } this.addAttributes(node, nsContext, descriptor, val, attrs); @@ -349,32 +403,41 @@ class XMLHandler { var qname = attrDescriptors[i].qname; attributes[qname.name] = attrDescriptors[i]; } - if (attrs != null && typeof attrs === 'object') { + if (attrs != null && typeof attrs === "object") { for (let p in attrs) { let child = attrs[p]; // if field is $xsiType add xsi:type attribute if (p === this.options.xsiTypeKey) { let xsiType; - if(typeof child === 'object' && typeof child.type !== 'undefined') { + if (typeof child === "object" && typeof child.type !== "undefined") { // $xsiType has two fields - type, xmlns xsiType = QName.parse(child.type, child.xmlns); } else { xsiType = QName.parse(child); } - declareNamespace(nsContext, node, 'xsi', helper.namespaces.xsi); - let mapping = declareNamespace(nsContext, node, xsiType.prefix, - xsiType.nsURI); + declareNamespace(nsContext, node, "xsi", helper.namespaces.xsi); + let mapping = declareNamespace( + nsContext, + node, + xsiType.prefix, + xsiType.nsURI + ); let prefix = mapping ? mapping.prefix : xsiType.prefix; - node.attribute('xsi:type', prefix ? prefix + ':' + xsiType.name : - xsiType.name); + node.attribute( + "xsi:type", + prefix ? prefix + ":" + xsiType.name : xsiType.name + ); continue; } let childDescriptor = attributes[p]; if (childDescriptor == null) { if (this.options.ignoreUnknownProperties) continue; else { - childDescriptor = - new AttributeDescriptor(QName.parse(p), null, 'unqualified'); + childDescriptor = new AttributeDescriptor( + QName.parse(p), + null, + "unqualified" + ); } } this.jsonToXml(node, nsContext, childDescriptor, child); @@ -383,35 +446,49 @@ class XMLHandler { } static createSOAPEnvelope(prefix, nsURI) { - prefix = prefix || 'soap'; - var doc = xmlBuilder.create(prefix + ':Envelope', - {version: '1.0', encoding: 'UTF-8', standalone: true}); - nsURI = nsURI || 'http://schemas.xmlsoap.org/soap/envelope/'; - doc.attribute('xmlns:' + prefix, - nsURI); - let header = doc.element(prefix + ':Header'); - let body = doc.element(prefix + ':Body'); + prefix = prefix || "soap"; + var doc = xmlBuilder.create(prefix + ":Envelope", { + version: "1.0", + encoding: "UTF-8", + standalone: true, + }); + nsURI = nsURI || "http://schemas.xmlsoap.org/soap/envelope/"; + doc.attribute("xmlns:" + prefix, nsURI); + let header = doc.element(prefix + ":Header"); + let body = doc.element(prefix + ":Body"); return { body: body, header: header, - doc: doc + doc: doc, }; } static createSOAPEnvelopeDescriptor(prefix, nsURI, parameterDescriptor) { - prefix = prefix || 'soap'; - nsURI = nsURI || 'http://schemas.xmlsoap.org/soap/envelope/'; + prefix = prefix || "soap"; + nsURI = nsURI || "http://schemas.xmlsoap.org/soap/envelope/"; var descriptor = new TypeDescriptor(); var envelopeDescriptor = new ElementDescriptor( - new QName(nsURI, 'Envelope', prefix), null, 'qualified', false); + new QName(nsURI, "Envelope", prefix), + null, + "qualified", + false + ); descriptor.addElement(envelopeDescriptor); var headerDescriptor = new ElementDescriptor( - new QName(nsURI, 'Header', prefix), null, 'qualified', false); + new QName(nsURI, "Header", prefix), + null, + "qualified", + false + ); var bodyDescriptor = new ElementDescriptor( - new QName(nsURI, 'Body', prefix), null, 'qualified', false); + new QName(nsURI, "Body", prefix), + null, + "qualified", + false + ); envelopeDescriptor.addElement(headerDescriptor); envelopeDescriptor.addElement(bodyDescriptor); @@ -425,17 +502,29 @@ class XMLHandler { } if (parameterDescriptor && parameterDescriptor.faults) { - var xsdStr = new QName(helper.namespaces.xsd, 'string', 'xsd'); + var xsdStr = new QName(helper.namespaces.xsd, "string", "xsd"); var faultDescriptor = new ElementDescriptor( - new QName(nsURI, 'Fault', prefix), null, 'qualified', false); + new QName(nsURI, "Fault", prefix), + null, + "qualified", + false + ); faultDescriptor.addElement( - new ElementDescriptor(nsURI, 'faultcode', xsdStr, 'qualified', false)); + new ElementDescriptor(nsURI, "faultcode", xsdStr, "qualified", false) + ); faultDescriptor.addElement( - new ElementDescriptor(nsURI, 'faultstring', xsdStr, 'qualified', false)); + new ElementDescriptor(nsURI, "faultstring", xsdStr, "qualified", false) + ); faultDescriptor.addElement( - new ElementDescriptor(nsURI, 'faultactor', xsdStr, 'qualified', false)); - var detailDescriptor = - new ElementDescriptor(nsURI, 'detail', null, 'qualified', false); + new ElementDescriptor(nsURI, "faultactor", xsdStr, "qualified", false) + ); + var detailDescriptor = new ElementDescriptor( + nsURI, + "detail", + null, + "qualified", + false + ); faultDescriptor.addElement(detailDescriptor); for (var f in parameterDescriptor.faults) { @@ -456,13 +545,13 @@ class XMLHandler { static parseXml(root, xml, cb) { let parser; let stringMode = true; - debug('XMLHandler parseXML. root: %j xml: %j', root, xml); - if (typeof xml === 'string') { + debug("XMLHandler parseXML. root: %j xml: %j", root, xml); + if (typeof xml === "string") { stringMode = true; - parser = sax.parser(true, {opt: {xmlns: true}}); + parser = sax.parser(true, { opt: { xmlns: true } }); } else if (xml instanceof stream.Readable) { stringMode = false; - parser = sax.createStream(true, {opt: {xmlns: true}}); + parser = sax.createStream(true, { opt: { xmlns: true } }); } if (!root) { root = xmlBuilder.begin(); @@ -470,12 +559,12 @@ class XMLHandler { let current = root; let stack = [root]; - parser.onerror = function(e) { + parser.onerror = function (e) { // an error happened. if (cb) process.nextTick(cb); }; - parser.ontext = function(text) { + parser.ontext = function (text) { // got some text. t is the string of text. if (current.isDocument) return; text = text.trim(); @@ -484,7 +573,7 @@ class XMLHandler { } }; - parser.oncdata = function(text) { + parser.oncdata = function (text) { if (current.isDocument) return; text = text.trim(); if (text) { @@ -492,7 +581,7 @@ class XMLHandler { } }; - parser.onopentag = function(node) { + parser.onopentag = function (node) { // opened a tag. node has "name" and "attributes" let element = current.element(node.name); if (node.attributes) { @@ -502,18 +591,19 @@ class XMLHandler { current = element; }; - parser.onclosetag = function(nsName) { + parser.onclosetag = function (nsName) { var top = stack.pop(); assert(top === current); assert(top.name === nsName); current = stack[stack.length - 1]; }; - parser.onend = function() { - if (cb) process.nextTick(function() { - // parser stream is done, and ready to have more stuff written to it. - cb && cb(null, root); - }); + parser.onend = function () { + if (cb) + process.nextTick(function () { + // parser stream is done, and ready to have more stuff written to it. + cb && cb(null, root); + }); }; if (stringMode) { @@ -545,15 +635,18 @@ class XMLHandler { } xmlToJson(nsContext, xml, descriptor) { + if (xml.includes("An error occurred while processing the service request.")) + xml = xml.replace(/\n/g, ""); var self = this; var p = sax.parser(true); nsContext = nsContext || new NamespaceContext(); var root = {}; - var refs = {}, id; // {id: {hrefs:[], obj:}, ...} - var stack = [{name: null, object: root, descriptor: descriptor}]; + var refs = {}, + id; // {id: {hrefs:[], obj:}, ...} + var stack = [{ name: null, object: root, descriptor: descriptor }]; var options = this.options; - p.onopentag = function(node) { + p.onopentag = function (node) { nsContext.pushContext(); var top = stack[stack.length - 1]; var descriptor = top.descriptor; @@ -565,7 +658,7 @@ class XMLHandler { // Register namespaces 1st for (let a in attrs) { if (/^xmlns:|^xmlns$/.test(a)) { - let prefix = (a === 'xmlns') ? '' : a.substring(6); + let prefix = a === "xmlns" ? "" : a.substring(6); nsContext.addNamespace(prefix, attrs[a]); } } @@ -579,19 +672,19 @@ class XMLHandler { var xsiXmlns = null; if (nsContext.getNamespaceURI(qname.prefix) === helper.namespaces.xsi) { // Handle xsi:* - if (qname.name == 'nil') { + if (qname.name == "nil") { // xsi:nil - if (attrs[a] === 'true') { + if (attrs[a] === "true") { obj = null; } continue; - } else if (qname.name === 'type') { + } else if (qname.name === "type") { // xsi:type isXsiType = true; xsiType = attrs[a]; xsiType = QName.parse(xsiType); attrs[a] = xsiType.name; - if(xsiType.prefix){ + if (xsiType.prefix) { xsiXmlns = nsContext.getNamespaceURI(xsiType.prefix); } } @@ -624,16 +717,17 @@ class XMLHandler { if (attrs.href != null) { id = attrs.href.substr(1); if (refs[id] === undefined) { - refs[id] = {hrefs: [], object: null}; + refs[id] = { hrefs: [], object: null }; } refs[id].hrefs.push({ - parent: top.object, key: elementQName.name, object: obj + parent: top.object, + key: elementQName.name, + object: obj, }); } id = attrs.id; if (id != null) { - if (refs[id] === undefined) - refs[id] = {hrefs: [], object: null}; + if (refs[id] === undefined) refs[id] = { hrefs: [], object: null }; } stack.push({ @@ -644,7 +738,7 @@ class XMLHandler { }); }; - p.onclosetag = function(nsName) { + p.onclosetag = function (nsName) { var elementName = QName.parse(nsName).name; nsContext.popContext(); var current = stack.pop(); @@ -653,7 +747,7 @@ class XMLHandler { top.object = {}; } if (top.object !== null) { - if (typeof top.object === 'object' && elementName in top.object) { + if (typeof top.object === "object" && elementName in top.object) { // The element exist already, let's create an array let val = top.object[elementName]; if (Array.isArray(val)) { @@ -676,11 +770,7 @@ class XMLHandler { } }; - p.oncdata = function(text) { - text = text && text.trim(); - if (!text.length) - return; - + p.oncdata = function (text) { if (/<\?xml[\s\S]+\?>/.test(text)) { text = self.xmlToJson(null, text); } @@ -688,16 +778,12 @@ class XMLHandler { p.handleJsonObject(text); }; - p.handleJsonObject = function(text) { + p.handleJsonObject = function (text) { var top = stack[stack.length - 1]; self._processText(top, text); }; - p.ontext = function(text) { - text = text && text.trim(); - if (!text.length) - return; - + p.ontext = function (text) { var top = stack[stack.length - 1]; var descriptor = top.descriptor; var value = parseValue(text, descriptor); @@ -707,7 +793,7 @@ class XMLHandler { p.write(xml).close(); // merge obj with href - var merge = function(href, obj) { + var merge = function (href, obj) { for (var j in obj) { if (obj.hasOwnProperty(j)) { href.object[j] = obj[j]; @@ -735,7 +821,7 @@ class XMLHandler { } //couldn't process error message for neither soap 1.1 nor soap 1.2 fault. Nothing else can be done at this point. Send a generic error message. if (errorMessage == null) { - errorMessage = 'Error occurred processing Fault response.'; + errorMessage = "Error occurred processing Fault response."; } var error = new Error(errorMessage); error.root = root; @@ -746,36 +832,40 @@ class XMLHandler { } return root; } - } function getSoap11FaultErrorMessage(faultBody) { var errorMessage = null; - var faultcode = selectn('faultcode.$value', faultBody)|| - selectn('faultcode', faultBody); - if (faultcode) { //soap 1.1 fault - errorMessage = ' '; + var faultcode = + selectn("faultcode.$value", faultBody) || selectn("faultcode", faultBody); + if (faultcode) { + //soap 1.1 fault + errorMessage = " "; //All of the soap 1.1 fault elements should contain string value except detail element which may be a complex type or plain text (string) - if (typeof faultcode == 'string') { - errorMessage = 'faultcode: ' + faultcode; - } - var faultstring = selectn('faultstring.$value', faultBody) || - selectn('faultstring', faultBody); - if (faultstring && (typeof faultstring == 'string')) { - errorMessage = errorMessage + ' faultstring: ' + faultstring; - } - var faultactor = selectn('faultactor.$value', faultBody) || - selectn('faultactor', faultBody); - if (faultactor && (typeof faultactor == 'string')) { - errorMessage = errorMessage + ' faultactor: ' + faultactor; - } - var detail = selectn('detail.$value', faultBody) || - selectn('detail', faultBody); + if (typeof faultcode == "string") { + errorMessage = "faultcode: " + faultcode; + } + var faultstring = + selectn("faultstring.$value", faultBody) || + selectn("faultstring", faultBody); + if (faultstring && typeof faultstring == "string") { + errorMessage = errorMessage + " faultstring: " + faultstring; + } + var faultactor = + selectn("faultactor.$value", faultBody) || + selectn("faultactor", faultBody); + if (faultactor && typeof faultactor == "string") { + errorMessage = errorMessage + " faultactor: " + faultactor; + } + var detail = + selectn("detail.$value", faultBody) || selectn("detail", faultBody); if (detail != null) { - if (typeof detail == 'string') { //plain text - errorMessage = errorMessage + ' detail: ' + detail; - } else { //XML type defined in wsdl - errorMessage = errorMessage + ' detail: ' + JSON.stringify(detail); + if (typeof detail == "string") { + //plain text + errorMessage = errorMessage + " detail: " + detail; + } else { + //XML type defined in wsdl + errorMessage = errorMessage + " detail: " + JSON.stringify(detail); } } } @@ -784,59 +874,57 @@ function getSoap11FaultErrorMessage(faultBody) { function getSoap12FaultErrorMessage(faultBody) { var errorMessage = null; - let code = selectn('Code', faultBody)|| - selectn('Code', faultBody); + let code = selectn("Code", faultBody) || selectn("Code", faultBody); if (code) { //soap 1.2 fault elements have child elements. Hence use JSON.stringify to formulate the error message. - errorMessage = ' '; - errorMessage = errorMessage + 'Code: ' + JSON.stringify(code); - var value = selectn('Value.$value', faultBody) || - selectn('Value', faultBody); + errorMessage = " "; + errorMessage = errorMessage + "Code: " + JSON.stringify(code); + var value = + selectn("Value.$value", faultBody) || selectn("Value", faultBody); if (value) { - errorMessage = errorMessage + ' ' + 'Value: ' + JSON.stringify(value); + errorMessage = errorMessage + " " + "Value: " + JSON.stringify(value); } - var subCode = selectn('Subcode.$value', faultBody) || - selectn('Subcode', faultBody); + var subCode = + selectn("Subcode.$value", faultBody) || selectn("Subcode", faultBody); if (subCode) { - errorMessage = errorMessage + ' ' + 'Subcode: ' + JSON.stringify(subCode); + errorMessage = errorMessage + " " + "Subcode: " + JSON.stringify(subCode); } - var reason = selectn('reason.$value', faultBody) || - selectn('Reason', faultBody); + var reason = + selectn("reason.$value", faultBody) || selectn("Reason", faultBody); if (reason) { - errorMessage = errorMessage + ' ' + 'Reason: ' + JSON.stringify(reason); + errorMessage = errorMessage + " " + "Reason: " + JSON.stringify(reason); } - var node = selectn('Node.$value', faultBody) || - selectn('Node', faultBody); + var node = selectn("Node.$value", faultBody) || selectn("Node", faultBody); if (node) { - errorMessage = errorMessage + ' ' + 'Node: ' + JSON.stringify(node); + errorMessage = errorMessage + " " + "Node: " + JSON.stringify(node); } - var role = selectn('Role.$value', faultBody) || - selectn('Role', faultBody); + var role = selectn("Role.$value", faultBody) || selectn("Role", faultBody); if (role) { - errorMessage = errorMessage + ' ' + 'Role: ' + JSON.stringify(role); + errorMessage = errorMessage + " " + "Role: " + JSON.stringify(role); } - var detail = selectn('Detail.$value', faultBody) || - selectn('Detail', faultBody); + var detail = + selectn("Detail.$value", faultBody) || selectn("Detail", faultBody); if (detail != null) { - if (typeof detail == 'string') { //plain text - errorMessage = errorMessage + ' Detail: ' + detail; - } else { //XML type defined in wsdl - errorMessage = errorMessage + ' Detail: ' + JSON.stringify(detail); + if (typeof detail == "string") { + //plain text + errorMessage = errorMessage + " Detail: " + detail; + } else { + //XML type defined in wsdl + errorMessage = errorMessage + " Detail: " + JSON.stringify(detail); } } } return errorMessage; } - function declareNamespace(nsContext, node, prefix, nsURI) { var mapping = nsContext.declareNamespace(prefix, nsURI); if (!mapping) { return false; } else if (node) { - if (typeof node.attribute === 'function') { + if (typeof node.attribute === "function") { // Some types of node such as XMLDummy does not allow attribute - node.attribute('xmlns:' + mapping.prefix, mapping.uri); + node.attribute("xmlns:" + mapping.prefix, mapping.uri); } return mapping; } @@ -844,40 +932,19 @@ function declareNamespace(nsContext, node, prefix, nsURI) { } function parseValue(text, descriptor) { - if (typeof text !== 'string') return text; - var value = text; - var jsType = descriptor && descriptor.jsType; - if (jsType === Date) { - var dateText = text; - // Checks for xs:date with tz, drops the tz - // because xs:date doesn't have a time to offset - // and JS Date object doesn't store an arbitrary tz - if(dateText.length === 16){ - dateText = text.substr(0, 10); - } - value = new Date(dateText); - } else if (jsType === Boolean) { - if (text === 'true' || text === '1') { - value = true; - } else { - value = false; - } - } else if (typeof jsType === 'function') { - value = jsType(text); - } - return value; + return text; } function toXmlDate(date) { date = new Date(date); var isoStr = date.toISOString(); - return isoStr.split('T')[0] + 'Z'; + return isoStr.split("T")[0] + "Z"; } function toXmlTime(date) { date = new Date(date); var isoStr = date.toISOString(); - return isoStr.split('T')[1]; + return isoStr.split("T")[1]; } function toXmlDateTime(date) { @@ -887,14 +954,6 @@ function toXmlDateTime(date) { } function toXmlDateOrTime(descriptor, val) { - if (!descriptor || !descriptor.type || val === null) return val; - if (descriptor.type.name === 'date') { - val = toXmlDate(val); - } else if (descriptor.type.name === 'time') { - val = toXmlTime(val); - } else if (descriptor.type.name === 'dateTime') { - val = toXmlDateTime(val); - } return val; }