http2: propagate session destroy code to streams
Currently, when an HTTP2 session is destroyed with a code, that code is not propagated to the destroy() call of the session's streams. This commit forwards any code used to destroy a session to its corresponding streams. PR-URL: https://github.com/nodejs/node/pull/28435 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
This commit is contained in:
parent
bf7edaa3c9
commit
f9632041dc
@ -942,6 +942,7 @@ class Http2Session extends EventEmitter {
|
||||
socket[kSession] = this;
|
||||
|
||||
this[kState] = {
|
||||
destroyCode: NGHTTP2_NO_ERROR,
|
||||
flags: SESSION_FLAGS_PENDING,
|
||||
goawayCode: null,
|
||||
goawayLastStreamID: null,
|
||||
@ -1206,6 +1207,7 @@ class Http2Session extends EventEmitter {
|
||||
|
||||
const state = this[kState];
|
||||
state.flags |= SESSION_FLAGS_DESTROYED;
|
||||
state.destroyCode = code;
|
||||
|
||||
// Clear timeout and remove timeout listeners
|
||||
this.setTimeout(0);
|
||||
@ -1937,10 +1939,13 @@ class Http2Stream extends Duplex {
|
||||
|
||||
debug(`Http2Stream ${this[kID] || '<pending>'} [Http2Session ` +
|
||||
`${sessionName(session[kType])}]: destroying stream`);
|
||||
const state = this[kState];
|
||||
const code = err != null ?
|
||||
NGHTTP2_INTERNAL_ERROR : (state.rstCode || NGHTTP2_NO_ERROR);
|
||||
|
||||
const state = this[kState];
|
||||
const sessionCode = session[kState].goawayCode ||
|
||||
session[kState].destroyCode;
|
||||
const code = err != null ?
|
||||
sessionCode || NGHTTP2_INTERNAL_ERROR :
|
||||
state.rstCode || sessionCode;
|
||||
const hasHandle = handle !== undefined;
|
||||
|
||||
if (!this.closed)
|
||||
|
54
test/parallel/test-http2-propagate-session-destroy-code.js
Normal file
54
test/parallel/test-http2-propagate-session-destroy-code.js
Normal file
@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const http2 = require('http2');
|
||||
const server = http2.createServer();
|
||||
const errRegEx = /Session closed with error code 7/;
|
||||
const destroyCode = http2.constants.NGHTTP2_REFUSED_STREAM;
|
||||
|
||||
server.on('error', common.mustNotCall());
|
||||
|
||||
server.on('session', (session) => {
|
||||
session.on('close', common.mustCall());
|
||||
session.on('error', common.mustCall((err) => {
|
||||
assert(errRegEx.test(err));
|
||||
assert.strictEqual(session.closed, false);
|
||||
assert.strictEqual(session.destroyed, true);
|
||||
}));
|
||||
|
||||
session.on('stream', common.mustCall((stream) => {
|
||||
stream.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(session.closed, false);
|
||||
assert.strictEqual(session.destroyed, true);
|
||||
assert(errRegEx.test(err));
|
||||
assert.strictEqual(stream.rstCode, destroyCode);
|
||||
}));
|
||||
|
||||
session.destroy(destroyCode);
|
||||
}));
|
||||
});
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const session = http2.connect(`http://localhost:${server.address().port}`);
|
||||
|
||||
session.on('error', common.mustCall((err) => {
|
||||
assert(errRegEx.test(err));
|
||||
assert.strictEqual(session.closed, false);
|
||||
assert.strictEqual(session.destroyed, true);
|
||||
}));
|
||||
|
||||
const stream = session.request({ [http2.constants.HTTP2_HEADER_PATH]: '/' });
|
||||
|
||||
stream.on('error', common.mustCall((err) => {
|
||||
assert(errRegEx.test(err));
|
||||
assert.strictEqual(stream.rstCode, destroyCode);
|
||||
}));
|
||||
|
||||
stream.on('close', common.mustCall(() => {
|
||||
server.close();
|
||||
}));
|
||||
}));
|
Loading…
x
Reference in New Issue
Block a user