From 82ea7058b6c25ee2c1467665c1b53b2b2b9ca139 Mon Sep 17 00:00:00 2001 From: Sagi Tsofan Date: Fri, 21 Sep 2018 00:59:22 +0300 Subject: [PATCH] lib: http server, friendly error messages Improved error message description for the http server binding errors. Currently changed only in `setupListenHandle`, but needs to be change all over. Added new `uvExceptionWithHostPort` function (+export) in `lib/internal/error.js` that extracts the error message defined by libuv, using the error code, and returns an error object with the full error description. example: old error message: `listen EADDRINUSE` new error message: `listen EADDRINUSE: Address already in use` Removed exportable function `_exceptionWithHostPort` from `lib/util.js` - exported by accident Replaced `exceptionWithHostPort` to the new function `uvExceptionWithHostPort` for a more detailed error. Fixes: https://github.com/nodejs/node/issues/22936 PR-URL: https://github.com/nodejs/node/pull/22995 Reviewed-By: Anna Henningsen Reviewed-By: Matteo Collina Reviewed-By: Sakthipriyan Vairamani Reviewed-By: James M Snell --- lib/internal/errors.js | 46 ++++++++++++++++++- lib/net.js | 10 ++-- .../parallel/test-net-server-listen-handle.js | 2 +- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 4094a40f6b5631..58eba742e08685 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -285,6 +285,46 @@ function uvException(ctx) { return err; } +/** + * This creates an error compatible with errors produced in the C++ + * This function should replace the deprecated + * `exceptionWithHostPort()` function. + * + * @param {number} err - A libuv error number + * @param {string} syscall + * @param {string} address + * @param {number} [port] + * @param {string} [additional] + * @returns {Error} + */ +function uvExceptionWithHostPort(err, syscall, address, port, additional) { + const [ code, uvmsg ] = errmap.get(err); + const message = `${syscall} ${code}: ${uvmsg}`; + let details = ''; + + if (port && port > 0) { + details = ` ${address}:${port}`; + } else if (address) { + details = ` ${address}`; + } + if (additional) { + details += ` - Local (${additional})`; + } + + // eslint-disable-next-line no-restricted-syntax + const ex = new Error(`${message}${details}`); + ex.code = code; + ex.errno = code; + ex.syscall = syscall; + ex.address = address; + if (port) { + ex.port = port; + } + + Error.captureStackTrace(ex, uvExceptionWithHostPort); + return ex; +} + /** * This used to be util._errnoException(). * @@ -314,8 +354,9 @@ function errnoException(err, syscall, original) { } /** - * This used to be util._exceptionWithHostPort(). - * + * Deprecated, new function is `uvExceptionWithHostPort()` + * New function added the error description directly + * from C++. this method for backwards compatibility * @param {number} err - A libuv error number * @param {string} syscall * @param {string} address @@ -437,6 +478,7 @@ module.exports = { errnoException, exceptionWithHostPort, uvException, + uvExceptionWithHostPort, isStackOverflowError, getMessage, SystemError, diff --git a/lib/net.js b/lib/net.js index f7d55ca6462920..33ce1f74eb2fba 100644 --- a/lib/net.js +++ b/lib/net.js @@ -84,7 +84,11 @@ const kLastWriteQueueSize = Symbol('lastWriteQueueSize'); let cluster; let dns; -const { errnoException, exceptionWithHostPort } = errors; +const { + errnoException, + exceptionWithHostPort, + uvExceptionWithHostPort +} = errors; const { kTimeout, @@ -1266,7 +1270,7 @@ function setupListenHandle(address, port, addressType, backlog, fd) { rval = createServerHandle(address, port, addressType, fd); if (typeof rval === 'number') { - var error = exceptionWithHostPort(rval, 'listen', address, port); + var error = uvExceptionWithHostPort(rval, 'listen', address, port); process.nextTick(emitErrorNT, this, error); return; } @@ -1283,7 +1287,7 @@ function setupListenHandle(address, port, addressType, backlog, fd) { var err = this._handle.listen(backlog || 511); if (err) { - var ex = exceptionWithHostPort(err, 'listen', address, port); + var ex = uvExceptionWithHostPort(err, 'listen', address, port); this._handle.close(); this._handle = null; defaultTriggerAsyncIdScope(this[async_id_symbol], diff --git a/test/parallel/test-net-server-listen-handle.js b/test/parallel/test-net-server-listen-handle.js index b1182221fcbd06..0d59bd76cad8a8 100644 --- a/test/parallel/test-net-server-listen-handle.js +++ b/test/parallel/test-net-server-listen-handle.js @@ -150,7 +150,7 @@ if (!common.isWindows) { // Windows doesn't support {fd: } net.createServer() .listen({ fd }, common.mustNotCall()) .on('error', common.mustCall(function(err) { - assert.strictEqual(String(err), 'Error: listen EINVAL'); + assert.strictEqual(String(err), 'Error: listen EINVAL: invalid argument'); this.close(); })); }