From ae506532e959d1a375970c05d76a07905d5609aa Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Sat, 28 Apr 2018 00:34:52 +0200 Subject: [PATCH] http2: compat avoid bind and propertly cleanup stream. --- lib/internal/http2/compat.js | 78 +++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/lib/internal/http2/compat.js b/lib/internal/http2/compat.js index d2aaa8838e2cbc..6e25b273018c92 100644 --- a/lib/internal/http2/compat.js +++ b/lib/internal/http2/compat.js @@ -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];