From bb475ab00fa970d4e06096e3cce99a1485b79cf1 Mon Sep 17 00:00:00 2001 From: Tony Brix Date: Thu, 18 Feb 2021 22:45:14 -0600 Subject: [PATCH] fix: emit error event if other error events are not listened to --- lib/client/client.js | 16 ++++++- lib/errors/index.js | 3 ++ test/client.test.js | 103 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 119 insertions(+), 3 deletions(-) diff --git a/lib/client/client.js b/lib/client/client.js index d090cca..bdff844 100644 --- a/lib/client/client.js +++ b/lib/client/client.js @@ -1029,9 +1029,9 @@ Client.prototype.connect = function connect () { self.log.debug('failed to connect after %d attempts', failAfter) // Communicate the last-encountered error if (err instanceof ConnectionError) { - self.emit('connectTimeout', err) + self.emitError('connectTimeout', err) } else if (err.code === 'ECONNREFUSED') { - self.emit('connectRefused', err) + self.emitError('connectRefused', err) } else { self.emit('error', err) } @@ -1277,3 +1277,15 @@ Client.prototype._sendSocket = function _sendSocket (message, return callback(e) } } + +Client.prototype.emitError = function emitError (event, err) { + if (event !== 'error' && err && this.listenerCount(event) === 0) { + if (typeof err === 'string') { + err = event + ': ' + err + } else if (err.message) { + err.message = event + ': ' + err.message + } + this.emit('error', err) + } + this.emit(event, err) +} diff --git a/lib/errors/index.js b/lib/errors/index.js index a6c3826..07c5745 100644 --- a/lib/errors/index.js +++ b/lib/errors/index.js @@ -32,6 +32,9 @@ Object.defineProperties(LDAPError.prototype, { get: function getMessage () { return this.lde_message || this.name }, + set: function setMessage (message) { + this.lde_message = message + }, configurable: false }, dn: { diff --git a/test/client.test.js b/test/client.test.js index 40a93ce..d248abf 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -367,7 +367,7 @@ tap.test('createClient', t => { ) }) - tap.test('exception from bad createClient parameter (issue #418)', t => { + t.test('exception from bad createClient parameter (issue #418)', t => { try { // This port number is totally invalid. It will cause the URL parser // to throw an exception that should be caught. @@ -387,6 +387,9 @@ tap.test('createClient', t => { ], connectTimeout: 1 }) + client.on('connectTimeout', () => {}) + client.on('connectError', () => {}) + client.on('connectRefused', () => {}) t.equal(client.urls.length, 2) }) @@ -1513,6 +1516,8 @@ tap.test('connection refused', function (t) { url: `ldap://0.0.0.0:${unusedPortNumber}` }) + client.on('connectRefused', () => {}) + client.bind('cn=root', 'secret', function (err, res) { t.true(err) t.type(err, Error) @@ -1531,6 +1536,8 @@ tap.test('connection timeout', function (t) { timeout: 1 }) + client.on('connectTimeout', () => {}) + let done = false setTimeout(function () { @@ -1549,3 +1556,97 @@ tap.test('connection timeout', function (t) { }) }) }) + +tap.only('emitError', function (t) { + t.test('connectTimeout', function (t) { + getPort().then(function (unusedPortNumber) { + const client = ldap.createClient({ + url: `ldap://example.org:${unusedPortNumber}`, + connectTimeout: 1, + timeout: 1 + }) + + const timeout = setTimeout(function () { + throw new Error('LDAPJS waited for the server for too long') + }, 2000) + + client.on('error', (err) => { + t.fail(err) + }) + client.on('connectTimeout', (err) => { + t.true(err) + t.type(err, Error) + t.equals(err.message, 'connection timeout') + clearTimeout(timeout) + t.end() + }) + + client.bind('cn=root', 'secret', () => {}) + }) + }) + + t.test('connectTimeout to error', function (t) { + getPort().then(function (unusedPortNumber) { + const client = ldap.createClient({ + url: `ldap://example.org:${unusedPortNumber}`, + connectTimeout: 1, + timeout: 1 + }) + + const timeout = setTimeout(function () { + throw new Error('LDAPJS waited for the server for too long') + }, 2000) + + client.on('error', (err) => { + t.true(err) + t.type(err, Error) + t.equals(err.message, 'connectTimeout: connection timeout') + clearTimeout(timeout) + t.end() + }) + + client.bind('cn=root', 'secret', () => {}) + }) + }) + + t.test('connectRefused', function (t) { + getPort().then(function (unusedPortNumber) { + const client = ldap.createClient({ + url: `ldap://0.0.0.0:${unusedPortNumber}` + }) + + client.on('error', (err) => { + t.fail(err) + }) + client.on('connectRefused', (err) => { + t.true(err) + t.type(err, Error) + t.equals(err.message, `connect ECONNREFUSED 0.0.0.0:${unusedPortNumber}`) + t.equals(err.code, 'ECONNREFUSED') + t.end() + }) + + client.bind('cn=root', 'secret', () => {}) + }) + }) + + t.test('connectRefused to error', function (t) { + getPort().then(function (unusedPortNumber) { + const client = ldap.createClient({ + url: `ldap://0.0.0.0:${unusedPortNumber}` + }) + + client.on('error', (err) => { + t.true(err) + t.type(err, Error) + t.equals(err.message, `connectRefused: connect ECONNREFUSED 0.0.0.0:${unusedPortNumber}`) + t.equals(err.code, 'ECONNREFUSED') + t.end() + }) + + client.bind('cn=root', 'secret', () => {}) + }) + }) + + t.end() +})