http2: emit close event if request aborted
Fix Http2ServerRequest and Http2ServerResponse to emit close event if the request is aborted before response.end can be called. Fixes: https://github.com/nodejs/node/issues/15385 PR-URL: https://github.com/nodejs/node/pull/15415 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
de51717c3e
commit
8fa5fcc0ba
@ -123,10 +123,17 @@ function onStreamClosedResponse() {
|
||||
res.emit('finish');
|
||||
}
|
||||
|
||||
function onAborted(hadError, code) {
|
||||
function onStreamAbortedRequest(hadError, code) {
|
||||
if ((this.writable) ||
|
||||
(this._readableState && !this._readableState.ended)) {
|
||||
this.emit('aborted', hadError, code);
|
||||
this.emit('close');
|
||||
}
|
||||
}
|
||||
|
||||
function onStreamAbortedResponse() {
|
||||
if (this.writable) {
|
||||
this.emit('close');
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,7 +158,7 @@ class Http2ServerRequest extends Readable {
|
||||
stream.on('end', onStreamEnd);
|
||||
stream.on('error', onStreamError);
|
||||
stream.on('close', onStreamClosedRequest);
|
||||
stream.on('aborted', onAborted.bind(this));
|
||||
stream.on('aborted', onStreamAbortedRequest.bind(this));
|
||||
const onfinish = this[kFinish].bind(this);
|
||||
stream.on('streamClosed', onfinish);
|
||||
stream.on('finish', onfinish);
|
||||
@ -274,6 +281,7 @@ class Http2ServerResponse extends Stream {
|
||||
this.writable = true;
|
||||
stream.on('drain', onStreamResponseDrain);
|
||||
stream.on('close', onStreamClosedResponse);
|
||||
stream.on('aborted', onStreamAbortedResponse.bind(this));
|
||||
const onfinish = this[kFinish].bind(this);
|
||||
stream.on('streamClosed', onfinish);
|
||||
stream.on('finish', onfinish);
|
||||
|
41
test/parallel/test-http2-compat-serverresponse-close.js
Normal file
41
test/parallel/test-http2-compat-serverresponse-close.js
Normal file
@ -0,0 +1,41 @@
|
||||
// Flags: --expose-http2 --expose-internals
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
const h2 = require('http2');
|
||||
|
||||
// Server request and response should receive close event
|
||||
// if the connection was terminated before response.end
|
||||
// could be called or flushed
|
||||
|
||||
const server = h2.createServer(common.mustCall((req, res) => {
|
||||
res.writeHead(200);
|
||||
res.write('a');
|
||||
|
||||
req.on('close', common.mustCall());
|
||||
res.on('close', common.mustCall());
|
||||
}));
|
||||
server.listen(0);
|
||||
|
||||
server.on('listening', function() {
|
||||
const port = server.address().port;
|
||||
|
||||
const url = `http://localhost:${port}`;
|
||||
const client = h2.connect(url, common.mustCall(function() {
|
||||
const headers = {
|
||||
':path': '/foobar',
|
||||
':method': 'GET',
|
||||
':scheme': 'http',
|
||||
':authority': `localhost:${port}`,
|
||||
};
|
||||
const request = client.request(headers);
|
||||
request.on('data', common.mustCall(function(chunk) {
|
||||
// cause an error on the server side
|
||||
client.destroy();
|
||||
server.close();
|
||||
}));
|
||||
request.end();
|
||||
}));
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user