Skip to content

Commit 99d74e8

Browse files
committed
Merge pull request #93 from patricklodder/detailed_errors_cp
Clientside detailed error reporting
2 parents 98f700c + 7676a48 commit 99d74e8

File tree

3 files changed

+80
-3
lines changed

3 files changed

+80
-3
lines changed

README.md

+28
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,34 @@ var client = xmlrpc.createClient('YOUR_ENDPOINT');
170170
client.methodCall('YOUR_METHOD', [new YourType(yourVariable)], yourCallback);
171171
```
172172

173+
### To Debug (client-side)
174+
175+
Error callbacks on the client are enriched with request and response
176+
information and the returned body as long as a http connection was made,
177+
to aide with request debugging. Example:
178+
179+
```javascript
180+
var client = xmlrpc.createClient({ host: 'example.com', port: 80 });
181+
client.methodCall('FAULTY_METHOD', [], function (error, value) {
182+
if (error) {
183+
console.log('error:', error);
184+
console.log('req headers:', error.req && error.req._header);
185+
console.log('res code:', error.res && error.res.statusCode);
186+
console.log('res body:', error.body);
187+
} else {
188+
console.log('value:', value);
189+
}
190+
});
191+
192+
// error: [Error: Unknown XML-RPC tag 'TITLE']
193+
// req headers: POST / HTTP/1.1
194+
// User-Agent: NodeJS XML-RPC Client
195+
// ...
196+
// res code: 200
197+
// res body: <!doctype html>
198+
// ...
199+
```
200+
173201
### To Test
174202

175203
[![Build

lib/client.js

+20-2
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,31 @@ Client.prototype.methodCall = function methodCall(method, params, callback) {
104104
options.headers['Content-Length'] = Buffer.byteLength(xml, 'utf8')
105105
this.headersProcessors.composeRequest(options.headers)
106106
var request = transport.request(options, function(response) {
107+
108+
var body = []
109+
response.on('data', function (chunk) { body.push(chunk) })
110+
111+
function __enrichError (err) {
112+
Object.defineProperty(err, 'req', { value: request })
113+
Object.defineProperty(err, 'res', { value: response })
114+
Object.defineProperty(err, 'body', { value: body.join('') })
115+
return err
116+
}
117+
107118
if (response.statusCode == 404) {
108-
callback(new Error('Not Found'));
119+
callback(__enrichError(new Error('Not Found')))
109120
}
110121
else {
111122
this.headersProcessors.parseResponse(response.headers)
123+
112124
var deserializer = new Deserializer(options.responseEncoding)
113-
deserializer.deserializeMethodResponse(response, callback)
125+
126+
deserializer.deserializeMethodResponse(response, function(err, result) {
127+
if (err) {
128+
err = __enrichError(err)
129+
}
130+
callback(err, result)
131+
})
114132
}
115133
}.bind(this))
116134

test/client_test.js

+32-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var vows = require('vows')
55
, fs = require('fs')
66

77
const VALID_RESPONSE = fs.readFileSync(__dirname + '/fixtures/good_food/string_response.xml')
8+
const BROKEN_XML= fs.readFileSync(__dirname + '/fixtures/bad_food/broken_xml.xml')
89

910
vows.describe('Client').addBatch({
1011
//////////////////////////////////////////////////////////////////////
@@ -309,6 +310,36 @@ vows.describe('Client').addBatch({
309310
assert.equal(value, 'a=b')
310311
}
311312
}
312-
313+
, 'that responds with a malformed xml': {
314+
topic: function () {
315+
var that = this
316+
http.createServer(function(request, response) {
317+
response.writeHead(500, {'Content-Type': 'text/html'})
318+
response.write(BROKEN_XML)
319+
response.end()
320+
}).listen(9097, 'localhost', function () {
321+
var client = new Client({ host: 'localhost', port: 9097, path: '/' }, false)
322+
client.methodCall('broken', null, that.callback)
323+
})
324+
}
325+
, 'returns an error': function (error, value) {
326+
assert.instanceOf(error, Error)
327+
assert.match(error.message, /^Unexpected end/)
328+
}
329+
, 'returns the request object with the error': function (error, value) {
330+
assert.instanceOf(error, Error)
331+
assert.isObject(error.req)
332+
assert.isObject(error.req.connection)
333+
assert.isString(error.req._header)
334+
}
335+
, 'returns the response object with the error': function (error, value) {
336+
assert.instanceOf(error, Error)
337+
assert.isObject(error.res)
338+
assert.strictEqual(error.res.statusCode, 500)
339+
}
340+
, 'returns the body with the error': function (error, value) {
341+
assert.strictEqual(error.body, BROKEN_XML.toString())
342+
}
343+
}
313344
}
314345
}).export(module)

0 commit comments

Comments
 (0)