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 <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
pull/23050/merge
Sagi Tsofan 2018-09-21 00:59:22 +03:00 committed by Anna Henningsen
parent 3f08c004c5
commit 82ea7058b6
No known key found for this signature in database
GPG Key ID: 9C63F3A6CD2AD8F9
3 changed files with 52 additions and 6 deletions

View File

@ -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,

View File

@ -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],

View File

@ -150,7 +150,7 @@ if (!common.isWindows) { // Windows doesn't support {fd: <n>}
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();
}));
}