mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
net: support abortSignal in server.listen
PR-URL: https://github.com/nodejs/node/pull/36623 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
committed by
James M Snell
parent
51dfb869f3
commit
51b4367506
@@ -324,6 +324,9 @@ Listening on a file descriptor is not supported on Windows.
|
||||
<!-- YAML
|
||||
added: v0.11.14
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/36623
|
||||
description: AbortSignal support was added.
|
||||
- version: v11.4.0
|
||||
pr-url: https://github.com/nodejs/node/pull/23798
|
||||
description: The `ipv6Only` option is supported.
|
||||
@@ -344,6 +347,7 @@ changes:
|
||||
* `ipv6Only` {boolean} For TCP servers, setting `ipv6Only` to `true` will
|
||||
disable dual-stack support, i.e., binding to host `::` won't make
|
||||
`0.0.0.0` be bound. **Default:** `false`.
|
||||
* `signal` {AbortSignal} An AbortSignal that may be used to close a listening server.
|
||||
* `callback` {Function}
|
||||
functions.
|
||||
* Returns: {net.Server}
|
||||
@@ -375,6 +379,20 @@ Starting an IPC server as root may cause the server path to be inaccessible for
|
||||
unprivileged users. Using `readableAll` and `writableAll` will make the server
|
||||
accessible for all users.
|
||||
|
||||
If the `signal` option is enabled, calling `.abort()` on the corresponding
|
||||
`AbortController` is similar to calling `.close()` on the server:
|
||||
|
||||
```js
|
||||
const controller = new AbortController();
|
||||
server.listen({
|
||||
host: 'localhost',
|
||||
port: 80,
|
||||
signal: controller.signal
|
||||
});
|
||||
// Later, when you want to close the server.
|
||||
controller.abort();
|
||||
```
|
||||
|
||||
#### `server.listen(path[, backlog][, callback])`
|
||||
<!-- YAML
|
||||
added: v0.1.90
|
||||
|
||||
@@ -9,7 +9,7 @@ const eos = require('internal/streams/end-of-stream');
|
||||
const { ERR_INVALID_ARG_TYPE } = codes;
|
||||
|
||||
// This method is inlined here for readable-stream
|
||||
// It also does not allow for signal to not exist on the steam
|
||||
// It also does not allow for signal to not exist on the stream
|
||||
// https://github.com/nodejs/node/pull/36061#discussion_r533718029
|
||||
const validateAbortSignal = (signal, name) => {
|
||||
if (typeof signal !== 'object' ||
|
||||
|
||||
18
lib/net.js
18
lib/net.js
@@ -109,6 +109,7 @@ const {
|
||||
} = require('internal/errors');
|
||||
const { isUint8Array } = require('internal/util/types');
|
||||
const {
|
||||
validateAbortSignal,
|
||||
validateInt32,
|
||||
validatePort,
|
||||
validateString
|
||||
@@ -1148,6 +1149,22 @@ function afterConnect(status, handle, req, readable, writable) {
|
||||
}
|
||||
}
|
||||
|
||||
function addAbortSignalOption(self, options) {
|
||||
if (options?.signal === undefined) {
|
||||
return;
|
||||
}
|
||||
validateAbortSignal(options.signal, 'options.signal');
|
||||
const { signal } = options;
|
||||
const onAborted = () => {
|
||||
self.close();
|
||||
};
|
||||
if (signal.aborted) {
|
||||
process.nextTick(onAborted);
|
||||
} else {
|
||||
signal.addEventListener('abort', onAborted);
|
||||
self.once('close', () => signal.removeEventListener('abort', onAborted));
|
||||
}
|
||||
}
|
||||
|
||||
function Server(options, connectionListener) {
|
||||
if (!(this instanceof Server))
|
||||
@@ -1398,6 +1415,7 @@ Server.prototype.listen = function(...args) {
|
||||
listenInCluster(this, null, -1, -1, backlogFromArgs);
|
||||
return this;
|
||||
}
|
||||
addAbortSignalOption(this, options);
|
||||
// (handle[, backlog][, cb]) where handle is an object with a fd
|
||||
if (typeof options.fd === 'number' && options.fd >= 0) {
|
||||
listenInCluster(this, null, null, null, backlogFromArgs, options.fd);
|
||||
|
||||
33
test/parallel/test-net-server-listen-options-signal.js
Normal file
33
test/parallel/test-net-server-listen-options-signal.js
Normal file
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
|
||||
{
|
||||
// Test bad signal.
|
||||
const server = net.createServer();
|
||||
assert.throws(
|
||||
() => server.listen({ port: 0, signal: 'INVALID_SIGNAL' }),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError'
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// Test close.
|
||||
const server = net.createServer();
|
||||
const controller = new AbortController();
|
||||
server.on('close', common.mustCall());
|
||||
server.listen({ port: 0, signal: controller.signal });
|
||||
controller.abort();
|
||||
}
|
||||
|
||||
{
|
||||
// Test close with pre-aborted signal.
|
||||
const server = net.createServer();
|
||||
const controller = new AbortController();
|
||||
controller.abort();
|
||||
server.on('close', common.mustCall());
|
||||
server.listen({ port: 0, signal: controller.signal });
|
||||
}
|
||||
Reference in New Issue
Block a user