Skip to content

Commit

Permalink
http2: close idle connections when allowHTTP1 is true
Browse files Browse the repository at this point in the history
Fixes: #51493
  • Loading branch information
xsbchen committed Jan 30, 2024
1 parent 09da597 commit e78fcf2
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 1 deletion.
20 changes: 19 additions & 1 deletion lib/internal/http2/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const {
kIncomingMessage,
_checkIsHttpToken: checkIsHttpToken,
} = require('_http_common');
const { kServerResponse } = require('_http_server');
const { kServerResponse, Server: HttpServer, httpServerPreClose, setupConnectionsTracking } = require('_http_server');
const JSStreamSocket = require('internal/js_stream_socket');

const {
Expand Down Expand Up @@ -3180,6 +3180,11 @@ class Http2SecureServer extends TLSServer {
this[kOptions] = options;
this.timeout = 0;
this.on('newListener', setupCompat);
if (options.allowHTTP1 === true) {
this.headersTimeout = 60_000; // Minimum between 60 seconds or requestTimeout
this.requestTimeout = 300_000; // 5 minutes
this.on('listening', setupConnectionsTracking);
}
if (typeof requestListener === 'function')
this.on('request', requestListener);
this.on('tlsClientError', onErrorSecureServerSession);
Expand All @@ -3199,6 +3204,19 @@ class Http2SecureServer extends TLSServer {
validateSettings(settings);
this[kOptions].settings = { ...this[kOptions].settings, ...settings };
}

close() {
if (this[kOptions].allowHTTP1 === true) {
httpServerPreClose(this);
}
ReflectApply(TLSServer.prototype.close, this, arguments);
}

closeIdleConnections() {
if (this[kOptions].allowHTTP1 === true) {
ReflectApply(HttpServer.prototype.closeIdleConnections, this, arguments);
}
}
}

class Http2Server extends NETServer {
Expand Down
53 changes: 53 additions & 0 deletions test/parallel/test-http2-allow-http1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use strict';

const common = require('../common');
const fixtures = require('../common/fixtures');
if (!common.hasCrypto) common.skip('missing crypto');

const assert = require('assert');
const https = require('https');
const http2 = require('http2');

(async function main() {

Check failure on line 11 in test/parallel/test-http2-allow-http1.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

The result of an immediately-invoked async function needs to be used (e.g. with `.then(common.mustCall())`)
const server = http2.createSecureServer({
key: fixtures.readKey('agent1-key.pem'),
cert: fixtures.readKey('agent1-cert.pem'),
allowHTTP1: true,
});

server.on(
'request',
common.mustCall((req, res) => {
res.writeHead(200);
res.end();
})
);

server.on(
'close',
common.mustCall(() => {})

Check failure on line 28 in test/parallel/test-http2-allow-http1.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

Do not use an empty function, omit the parameter altogether
);

await new Promise((resolve) => server.listen(0, resolve));

await new Promise((resolve) =>
https.get(
`https://localhost:${server.address().port}`,
{
rejectUnauthorized: false,
headers: { connection: 'keep-alive' },
},
resolve
)
);

let serverClosed = false;
setImmediate(common.mustCall(() => {
assert.ok(serverClosed, 'server should been closed immediately');
}));
server.close(
common.mustSucceed(() => {
serverClosed = true;
})
);
})();

0 comments on commit e78fcf2

Please sign in to comment.