http2: avoid bind and properly clean up in compat

PR-URL: https://github.com/nodejs/node/pull/20374
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
This commit is contained in:
Robert Nagy 2018-04-28 00:34:52 +02:00 committed by Anatoli Papirovski
parent 187e641736
commit 0d762af48e
No known key found for this signature in database
GPG Key ID: 614E2E1ABEB4B2C0

View File

@ -19,7 +19,6 @@ const {
} = require('internal/errors').codes;
const { kSocket } = require('internal/http2/util');
const kFinish = Symbol('finish');
const kBeginSend = Symbol('begin-send');
const kState = Symbol('state');
const kStream = Symbol('stream');
@ -223,6 +222,27 @@ const proxySocketHandler = {
}
};
function onStreamCloseRequest() {
const req = this[kRequest];
if (req === undefined)
return;
const state = req[kState];
state.closed = true;
req.push(null);
// if the user didn't interact with incoming data and didn't pipe it,
// dump it for compatibility with http1
if (!state.didRead && !req._readableState.resumeScheduled)
req.resume();
this[kProxySocket] = null;
this[kRequest] = undefined;
req.emit('close');
}
class Http2ServerRequest extends Readable {
constructor(stream, headers, options, rawHeaders) {
super(options);
@ -246,7 +266,7 @@ class Http2ServerRequest extends Readable {
stream.on('end', onStreamEnd);
stream.on('error', onStreamError);
stream.on('aborted', onStreamAbortedRequest);
stream.on('close', this[kFinish].bind(this));
stream.on('close', onStreamCloseRequest);
this.on('pause', onRequestPause);
this.on('resume', onRequestResume);
}
@ -349,24 +369,30 @@ class Http2ServerRequest extends Readable {
return;
this[kStream].setTimeout(msecs, callback);
}
[kFinish]() {
const state = this[kState];
if (state.closed)
return;
state.closed = true;
this.push(null);
this[kStream][kRequest] = undefined;
// if the user didn't interact with incoming data and didn't pipe it,
// dump it for compatibility with http1
if (!state.didRead && !this._readableState.resumeScheduled)
this.resume();
this.emit('close');
}
}
function onStreamTrailersReady() {
this[kStream].sendTrailers(this[kTrailers]);
this.sendTrailers(this[kResponse][kTrailers]);
}
function onStreamCloseResponse() {
const res = this[kResponse];
if (res === undefined)
return;
const state = res[kState];
if (this.headRequest !== state.headRequest)
return;
state.closed = true;
this[kProxySocket] = null;
this[kResponse] = undefined;
res.emit('finish');
res.emit('close');
}
class Http2ServerResponse extends Stream {
@ -387,8 +413,8 @@ class Http2ServerResponse extends Stream {
this.writable = true;
stream.on('drain', onStreamDrain);
stream.on('aborted', onStreamAbortedResponse);
stream.on('close', this[kFinish].bind(this));
stream.on('wantTrailers', onStreamTrailersReady.bind(this));
stream.on('close', onStreamCloseResponse);
stream.on('wantTrailers', onStreamTrailersReady);
}
// User land modules such as finalhandler just check truthiness of this
@ -619,7 +645,7 @@ class Http2ServerResponse extends Stream {
this.writeHead(this[kState].statusCode);
if (isFinished)
this[kFinish]();
onStreamCloseResponse.call(stream);
else
stream.end();
@ -665,18 +691,6 @@ class Http2ServerResponse extends Stream {
this[kStream].respond(headers, options);
}
[kFinish]() {
const stream = this[kStream];
const state = this[kState];
if (state.closed || stream.headRequest !== state.headRequest)
return;
state.closed = true;
this[kProxySocket] = null;
stream[kResponse] = undefined;
this.emit('finish');
this.emit('close');
}
// TODO doesn't support callbacks
writeContinue() {
const stream = this[kStream];