http2: remove waitTrailers
listener after closing a stream
When `writeHeader` of `Http2ServerResponse` instance are called with 204, 205 and 304 status codes an underlying stream closes. If call `end` method after sending any of these status codes it will cause an error `TypeError: Cannot read property 'Symbol(trailers)' of undefined` because a reference to `Http2ServerResponse` instance associated with Http2Stream already was deleted. The closing of stream causes emitting `waitTrailers` event and, when this event handles inside `onStreamTrailerReady` handler, there is no reference to Http2ServerResponse instance. Fixes: https://github.com/nodejs/node/issues/21740 PR-URL: https://github.com/nodejs/node/pull/21764 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
This commit is contained in:
parent
fb87d8aa12
commit
8babbc5e45
@ -391,6 +391,8 @@ function onStreamCloseResponse() {
|
|||||||
state.closed = true;
|
state.closed = true;
|
||||||
|
|
||||||
this[kProxySocket] = null;
|
this[kProxySocket] = null;
|
||||||
|
|
||||||
|
this.removeListener('wantTrailers', onStreamTrailersReady);
|
||||||
this[kResponse] = undefined;
|
this[kResponse] = undefined;
|
||||||
|
|
||||||
res.emit('finish');
|
res.emit('finish');
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
if (!common.hasCrypto)
|
||||||
|
common.skip('missing crypto');
|
||||||
|
const h2 = require('http2');
|
||||||
|
|
||||||
|
// This test case ensures that calling of res.end after sending
|
||||||
|
// 204, 205 and 304 HTTP statuses will not cause an error
|
||||||
|
// See issue: https://github.com/nodejs/node/issues/21740
|
||||||
|
|
||||||
|
const {
|
||||||
|
HTTP_STATUS_NO_CONTENT,
|
||||||
|
HTTP_STATUS_RESET_CONTENT,
|
||||||
|
HTTP_STATUS_NOT_MODIFIED
|
||||||
|
} = h2.constants;
|
||||||
|
|
||||||
|
const statusWithouBody = [
|
||||||
|
HTTP_STATUS_NO_CONTENT,
|
||||||
|
HTTP_STATUS_RESET_CONTENT,
|
||||||
|
HTTP_STATUS_NOT_MODIFIED,
|
||||||
|
];
|
||||||
|
const STATUS_CODES_COUNT = statusWithouBody.length;
|
||||||
|
|
||||||
|
const server = h2.createServer(common.mustCall(function(req, res) {
|
||||||
|
res.writeHead(statusWithouBody.pop());
|
||||||
|
res.end();
|
||||||
|
}, STATUS_CODES_COUNT));
|
||||||
|
|
||||||
|
server.listen(0, common.mustCall(function() {
|
||||||
|
const url = `http://localhost:${server.address().port}`;
|
||||||
|
const client = h2.connect(url, common.mustCall(() => {
|
||||||
|
let responseCount = 0;
|
||||||
|
const closeAfterResponse = () => {
|
||||||
|
if (STATUS_CODES_COUNT === ++responseCount) {
|
||||||
|
client.destroy();
|
||||||
|
server.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let i = 0; i < STATUS_CODES_COUNT; i++) {
|
||||||
|
const request = client.request();
|
||||||
|
request.on('response', common.mustCall(closeAfterResponse));
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
}));
|
Loading…
x
Reference in New Issue
Block a user