diff --git a/docs/index.md b/docs/index.md index bdf8c00382..fb641066da 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3499,12 +3499,22 @@ This event is emitted when there is an error on the connection to the server tha ### Return Value -The first parameter is a string indicating the error type, which may be `badMessage` (meaning that rippled returned a malformed message), or one of the [rippled Universal Errors](https://ripple.com/build/rippled-apis/#universal-errors). The second parameter is a message explaining the error, or the message that caused the error in the case of `badMessage`. +The first parameter is a string indicating the error type: +* `badMessage` - rippled returned a malformed message +* `websocket` - the websocket library emitted an error +* one of the error codes found in the [rippled Universal Errors](https://ripple.com/build/rippled-apis/#universal-errors). + +The second parameter is a message explaining the error. + +The third parameter is: +* the message that caused the error for `badMessage` +* the error object emitted for `websocket` +* the parsed response for rippled errors ### Example ```javascript -api.on('error', (errorCode, errorMessage) => { +api.on('error', (errorCode, errorMessage, data) => { console.log(errorCode + ': ' + errorMessage); }); ``` diff --git a/docs/src/events.md.ejs b/docs/src/events.md.ejs index 6353f4b927..11fe3ba319 100644 --- a/docs/src/events.md.ejs +++ b/docs/src/events.md.ejs @@ -24,12 +24,22 @@ This event is emitted when there is an error on the connection to the server tha ### Return Value -The first parameter is a string indicating the error type, which may be `badMessage` (meaning that rippled returned a malformed message), or one of the [rippled Universal Errors](https://ripple.com/build/rippled-apis/#universal-errors). The second parameter is a message explaining the error, or the message that caused the error in the case of `badMessage`. +The first parameter is a string indicating the error type: +* `badMessage` - rippled returned a malformed message +* `websocket` - the websocket library emitted an error +* one of the error codes found in the [rippled Universal Errors](https://ripple.com/build/rippled-apis/#universal-errors). + +The second parameter is a message explaining the error. + +The third parameter is: +* the message that caused the error for `badMessage` +* the error object emitted for `websocket` +* the parsed response for rippled errors ### Example ```javascript -api.on('error', (errorCode, errorMessage) => { +api.on('error', (errorCode, errorMessage, data) => { console.log(errorCode + ': ' + errorMessage); }); ``` diff --git a/src/api.js b/src/api.js index ce6c636575..adeef1395b 100644 --- a/src/api.js +++ b/src/api.js @@ -85,8 +85,8 @@ class RippleAPI extends EventEmitter { this.connection.on('ledgerClosed', message => { this.emit('ledger', server.formatLedgerClose(message)); }); - this.connection.on('error', (type, info) => { - this.emit('error', type, info); + this.connection.on('error', (errorCode, errorMessage, data) => { + this.emit('error', errorCode, errorMessage, data); }); } else { // use null object pattern to provide better error message if user diff --git a/src/broadcast.js b/src/broadcast.js index 122c3defda..041ab31501 100644 --- a/src/broadcast.js +++ b/src/broadcast.js @@ -37,7 +37,8 @@ class RippleAPIBroadcast extends RippleAPI { apis.forEach(api => { api.on('ledger', this.onLedgerEvent.bind(this)); - api.on('error', (type, info) => this.emit('error', type, info)); + api.on('error', (errorCode, errorMessage, data) => + this.emit('error', errorCode, errorMessage, data)); }); } diff --git a/src/common/connection.js b/src/common/connection.js index f0dfa0ab6a..cb87dbefd6 100644 --- a/src/common/connection.js +++ b/src/common/connection.js @@ -55,7 +55,7 @@ class Connection extends EventEmitter { } return [data.type, data]; } else if (data.type === undefined && data.error) { - return ['error', data.error, data.error_message]; // e.g. slowDown + return ['error', data.error, data.error_message, data]; // e.g. slowDown } throw new ResponseFormatError('unrecognized message type: ' + data.type); } @@ -68,7 +68,7 @@ class Connection extends EventEmitter { try { parameters = this._parseMessage(message); } catch (error) { - this.emit('error', 'badMessage', message); + this.emit('error', 'badMessage', error.message, message); return; } // we don't want this inside the try/catch or exceptions in listener @@ -161,6 +161,12 @@ class Connection extends EventEmitter { this._ws.once('open', resolve); } else { this._ws = this._createWebSocket(); + // when an error causes the connection to close, the close event + // should still be emitted; the "ws" documentation says: "The close + // event is also emitted when then underlying net.Socket closes the + // connection (end or close)." + this._ws.on('error', error => + this.emit('error', 'websocket', error.messsage, error)); this._ws.on('message', this._onMessage.bind(this)); this._onUnexpectedCloseBound = this._onUnexpectedClose.bind(this); this._ws.once('close', this._onUnexpectedCloseBound); diff --git a/test/connection-test.js b/test/connection-test.js index 870861ad17..24f2dd884b 100644 --- a/test/connection-test.js +++ b/test/connection-test.js @@ -227,8 +227,9 @@ describe('Connection', function() { }); it('invalid message id', function(done) { - this.api.on('error', (type, message) => { - assert.strictEqual(type, 'badMessage'); + this.api.on('error', (errorCode, errorMessage, message) => { + assert.strictEqual(errorCode, 'badMessage'); + assert.strictEqual(errorMessage, 'valid id not found in response'); assert.strictEqual(message, '{"type":"response","id":"must be integer"}'); done(); @@ -239,9 +240,10 @@ describe('Connection', function() { }); it('propagate error message', function(done) { - this.api.on('error', (type, message) => { - assert.strictEqual(type, 'slowDown'); - assert.strictEqual(message, 'slow down'); + this.api.on('error', (errorCode, errorMessage, data) => { + assert.strictEqual(errorCode, 'slowDown'); + assert.strictEqual(errorMessage, 'slow down'); + assert.deepEqual(data, {error: 'slowDown', error_message: 'slow down'}); done(); }); this.api.connection._onMessage(JSON.stringify({ @@ -250,8 +252,9 @@ describe('Connection', function() { }); it('unrecognized message type', function(done) { - this.api.on('error', (type, message) => { - assert.strictEqual(type, 'badMessage'); + this.api.on('error', (errorCode, errorMessage, message) => { + assert.strictEqual(errorCode, 'badMessage'); + assert.strictEqual(errorMessage, 'unrecognized message type: unknown'); assert.strictEqual(message, '{"type":"unknown"}'); done(); });