diff --git a/lib/client.js b/lib/client.js index a6c9c719c..c14be60d2 100644 --- a/lib/client.js +++ b/lib/client.js @@ -16,7 +16,8 @@ var HttpClient = require('./http'), events = require('events'), util = require('util'), debug = require('debug')('node-soap'), - url = require('url'); + url = require('url'), + _ = require('lodash'); var Client = function(wsdl, endpoint, options) { events.EventEmitter.call(this); @@ -215,6 +216,15 @@ Client.prototype._invoke = function(method, args, location, callback, options, e self.emit('message', message); self.emit('request', xml); + var tryJSONparse = function(body) { + try { + return JSON.parse(body); + } + catch(err) { + return undefined; + } + }; + req = self.httpClient.request(location, xml, function(err, response, body) { var result; var obj; @@ -225,14 +235,19 @@ Client.prototype._invoke = function(method, args, location, callback, options, e if (err) { callback(err); } else { + try { obj = self.wsdl.xmlToObject(body); } catch (error) { - //When the output element cannot be looked up in the wsdl, - //Then instead of sending the error, We pass the body in the response. + // 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. if(!output.$lookupTypes) { debug('Response element is not present. Unable to convert response xml to json.'); - return callback(null,response,body); + // If the response is JSON then return it as-is. + var json = _.isObject(body) ? body : tryJSONparse(body); + if (json) { + return callback(null, response, json); + } } error.response = response; error.body = body; diff --git a/lib/wsdl.js b/lib/wsdl.js index dfd196a42..d454f28aa 100644 --- a/lib/wsdl.js +++ b/lib/wsdl.js @@ -17,6 +17,7 @@ var assert = require('assert').ok; var stripBom = require('strip-bom'); var debug = require('debug')('node-soap'); var _ = require('lodash'); +var selectn = require('selectn'); var Primitives = { string: 1, @@ -1393,7 +1394,10 @@ WSDL.prototype.xmlToObject = function(xml) { if (root.Envelope) { var body = root.Envelope.Body; if (body.Fault) { - var error = new Error(body.Fault.faultcode + ': ' + body.Fault.faultstring + (body.Fault.detail ? ': ' + body.Fault.detail : '')); + var code = selectn('faultcode.$value', body.Fault); + var string = selectn('faultstring.$value', body.Fault); + var detail = selectn('detail.$value', body.Fault); + var error = new Error(code + ': ' + string + (detail ? ': ' + detail : '')); error.root = root; throw error; } diff --git a/package.json b/package.json index cc7600b2c..3914cc8c5 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,12 @@ }, "author": "Vinay Pulim ", "dependencies": { + "debug": "~0.7.4", "lodash": "~2.4.1", "request": ">=2.9.0", "sax": ">=0.6", - "strip-bom": "~0.3.1", - "debug": "~0.7.4" + "selectn": "^0.9.6", + "strip-bom": "~0.3.1" }, "repository": { "type": "git", diff --git a/test/client-test.js b/test/client-test.js index 1444b9fe8..c632636ac 100644 --- a/test/client-test.js +++ b/test/client-test.js @@ -516,4 +516,34 @@ describe('SOAP Client', function() { }); }); + + it('should return error in the call when Fault was returned', function(done) { + var server = null; + var hostname = '127.0.0.1'; + var port = 15099; + var baseUrl = 'http://' + hostname + ':' + port; + + server = http.createServer(function (req, res) { + res.statusCode = 200; + res.write("\nTesttest errortest detail"); + res.end(); + }).listen(port, hostname, function() { + soap.createClient(__dirname+'/wsdl/json_response.wsdl', function(err, client) { + assert.ok(client); + assert.ok(!err); + + client.MyOperation({}, function(err, result, body) { + server.close(); + server = null; + assert.ok(err); + assert.strictEqual(err.message, 'Test: test error: test detail'); + assert.ok(result); + assert.ok(body); + done(); + }); + }, baseUrl); + }); + + }); + });