Skip to content
12 changes: 12 additions & 0 deletions doc/api/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -1667,6 +1667,17 @@ to 8.0.0, which did not have a keep-alive timeout.
The socket timeout logic is set up on connection, so changing this value only
affects new connections to the server, not any existing connections.

### `server[Symbol.asyncDispose]()`

<!-- YAML
added: REPLACEME
-->

> Stability: 1 - Experimental

Calls [`server.close()`][] and returns a promise that fulfills when the
server has closed.

## Class: `http.ServerResponse`

<!-- YAML
Expand Down Expand Up @@ -3895,6 +3906,7 @@ Set the maximum number of idle HTTP parsers.
[`response.write(data, encoding)`]: #responsewritechunk-encoding-callback
[`response.writeContinue()`]: #responsewritecontinue
[`response.writeHead()`]: #responsewriteheadstatuscode-statusmessage-headers
[`server.close()`]: #serverclosecallback
[`server.headersTimeout`]: #serverheaderstimeout
[`server.keepAliveTimeout`]: #serverkeepalivetimeout
[`server.listen()`]: net.md#serverlisten
Expand Down
12 changes: 12 additions & 0 deletions doc/api/http2.md
Original file line number Diff line number Diff line change
Expand Up @@ -2070,6 +2070,17 @@ If `callback` is provided, it is not invoked until all active sessions have been
closed, although the server has already stopped allowing new sessions. See
[`net.Server.close()`][] for more details.

#### `server[Symbol.asyncDispose]()`

<!-- YAML
added: REPLACEME
-->

> Stability: 1 - Experimental

Calls [`server.close()`][] and returns a promise that fulfills when the
server has closed.

#### `server.setTimeout([msecs][, callback])`

<!-- YAML
Expand Down Expand Up @@ -4226,6 +4237,7 @@ you need to implement any fall-back behavior yourself.
[`response.write(data, encoding)`]: http.md#responsewritechunk-encoding-callback
[`response.writeContinue()`]: #responsewritecontinue
[`response.writeHead()`]: #responsewriteheadstatuscode-statusmessage-headers
[`server.close()`]: #serverclosecallback
[`server.maxHeadersCount`]: http.md#servermaxheaderscount
[`tls.Server.close()`]: tls.md#serverclosecallback
[`tls.TLSSocket`]: tls.md#class-tlstlssocket
Expand Down
12 changes: 12 additions & 0 deletions doc/api/https.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,17 @@ added: v0.1.90

See [`server.close()`][] in the `node:http` module.

### `server[Symbol.asyncDispose]()`

<!-- YAML
added: REPLACEME
-->

> Stability: 1 - Experimental

Calls [`server.close()`][httpsServerClose] and returns a promise that
fulfills when the server has closed.

### `server.closeAllConnections()`

<!-- YAML
Expand Down Expand Up @@ -571,4 +582,5 @@ headers: max-age=0; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; p
[`tls.connect()`]: tls.md#tlsconnectoptions-callback
[`tls.createSecureContext()`]: tls.md#tlscreatesecurecontextoptions
[`tls.createServer()`]: tls.md#tlscreateserveroptions-secureconnectionlistener
[httpsServerClose]: #serverclosecallback
[sni wiki]: https://en.wikipedia.org/wiki/Server_Name_Indication
7 changes: 7 additions & 0 deletions lib/_http_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@
const {
ArrayIsArray,
Error,
FunctionPrototypeCall,
MathMin,
ObjectKeys,
ObjectSetPrototypeOf,
RegExpPrototypeExec,
ReflectApply,
Symbol,
SymbolAsyncDispose,
SymbolFor,
} = primordials;

Expand Down Expand Up @@ -81,6 +83,7 @@ const {
} = codes;
const {
kEmptyObject,
promisify,
} = require('internal/util');
const {
validateInteger,
Expand Down Expand Up @@ -557,6 +560,10 @@ Server.prototype.close = function() {
ReflectApply(net.Server.prototype.close, this, arguments);
};

Server.prototype[SymbolAsyncDispose] = async function() {
return FunctionPrototypeCall(promisify(this.close), this);
};

Server.prototype.closeAllConnections = function() {
const connections = this[kConnections].all();

Expand Down
6 changes: 6 additions & 0 deletions lib/https.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ const {
ObjectSetPrototypeOf,
ReflectApply,
ReflectConstruct,
SymbolAsyncDispose,
} = primordials;

const {
assertCrypto,
kEmptyObject,
promisify,
} = require('internal/util');
assertCrypto();

Expand Down Expand Up @@ -110,6 +112,10 @@ Server.prototype.close = function() {
ReflectApply(tls.Server.prototype.close, this, arguments);
};

Server.prototype[SymbolAsyncDispose] = async function() {
return FunctionPrototypeCall(promisify(this.close), this);
};

/**
* Creates a new `https.Server` instance.
* @param {{
Expand Down
5 changes: 5 additions & 0 deletions lib/internal/http2/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const {
SafeSet,
StringPrototypeSlice,
Symbol,
SymbolAsyncDispose,
TypedArrayPrototypeGetLength,
Uint32Array,
Uint8Array,
Expand Down Expand Up @@ -3189,6 +3190,10 @@ class Http2Server extends NETServer {
validateSettings(settings);
this[kOptions].settings = { ...this[kOptions].settings, ...settings };
}

async [SymbolAsyncDispose]() {
return FunctionPrototypeCall(promisify(super.close), this);
}
}

Http2Server.prototype[EventEmitter.captureRejectionSymbol] = function(
Expand Down
14 changes: 14 additions & 0 deletions test/parallel/test-http-server-async-dispose.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const { createServer } = require('http');
const { kConnectionsCheckingInterval } = require('_http_server');

const server = createServer();

server.listen(0, common.mustCall(() => {
server.on('close', common.mustCall());
server[Symbol.asyncDispose]().then(common.mustCall(() => {
assert(server[kConnectionsCheckingInterval]._destroyed);
}));
}));
15 changes: 15 additions & 0 deletions test/parallel/test-http2-server-async-dispose.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict';

const common = require('../common');

if (!common.hasCrypto)
common.skip('missing crypto');

const http2 = require('http2');

const server = http2.createServer();

server.listen(0, common.mustCall(() => {
server.on('close', common.mustCall());
server[Symbol.asyncDispose]().then(common.mustCall());
}));
19 changes: 19 additions & 0 deletions test/parallel/test-https-server-async-dispose.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

const common = require('../common');

if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');
const { createServer } = require('https');
const { kConnectionsCheckingInterval } = require('_http_server');

const server = createServer();

server.listen(0, common.mustCall(() => {
server.on('close', common.mustCall());
server[Symbol.asyncDispose]().then(common.mustCall(() => {
assert(server[kConnectionsCheckingInterval]._destroyed);
}));
}));