http: use autoDestroy: true
in incoming message
Enable the default `autoDestroy: true` option in IncomingMessage. Refactor `_http_client` and `_http_server` to remove any manual destroying/closing of IncomingMessage. Refactor IncomingMessage `destroy` method to use the standard implementation of the stream module and move the early termination event emitting inside of it. PR-URL: https://github.com/nodejs/node/pull/33035 Refs: https://github.com/nodejs/node/issues/30625 Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
parent
eb14b10370
commit
55e83cbe95
@ -430,25 +430,13 @@ function socketCloseListener() {
|
|||||||
req.destroyed = true;
|
req.destroyed = true;
|
||||||
if (res) {
|
if (res) {
|
||||||
// Socket closed before we emitted 'end' below.
|
// Socket closed before we emitted 'end' below.
|
||||||
// TOOD(ronag): res.destroy(err)
|
|
||||||
if (!res.complete) {
|
if (!res.complete) {
|
||||||
res.aborted = true;
|
res.destroy(connResetException('aborted'));
|
||||||
res.emit('aborted');
|
|
||||||
if (res.listenerCount('error') > 0) {
|
|
||||||
res.emit('error', connResetException('aborted'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
req._closed = true;
|
req._closed = true;
|
||||||
req.emit('close');
|
req.emit('close');
|
||||||
if (!res.aborted && res.readable) {
|
if (!res.aborted && res.readable) {
|
||||||
res.on('end', function() {
|
|
||||||
this.destroyed = true;
|
|
||||||
this.emit('close');
|
|
||||||
});
|
|
||||||
res.push(null);
|
res.push(null);
|
||||||
} else {
|
|
||||||
res.destroyed = true;
|
|
||||||
res.emit('close');
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!req.socket._hadError) {
|
if (!req.socket._hadError) {
|
||||||
@ -697,7 +685,6 @@ function responseKeepAlive(req) {
|
|||||||
|
|
||||||
req.destroyed = true;
|
req.destroyed = true;
|
||||||
if (req.res) {
|
if (req.res) {
|
||||||
req.res.destroyed = true;
|
|
||||||
// Detach socket from IncomingMessage to avoid destroying the freed
|
// Detach socket from IncomingMessage to avoid destroying the freed
|
||||||
// socket in IncomingMessage.destroy().
|
// socket in IncomingMessage.destroy().
|
||||||
req.res.socket = null;
|
req.res.socket = null;
|
||||||
@ -752,13 +739,10 @@ function requestOnPrefinish() {
|
|||||||
function emitFreeNT(req) {
|
function emitFreeNT(req) {
|
||||||
req._closed = true;
|
req._closed = true;
|
||||||
req.emit('close');
|
req.emit('close');
|
||||||
if (req.res) {
|
|
||||||
req.res.emit('close');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.socket) {
|
if (req.socket) {
|
||||||
req.socket.emit('free');
|
req.socket.emit('free');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function tickOnSocket(req, socket) {
|
function tickOnSocket(req, socket) {
|
||||||
|
@ -54,7 +54,7 @@ function IncomingMessage(socket) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream.Readable.call(this, { autoDestroy: false, ...streamOptions });
|
Stream.Readable.call(this, streamOptions);
|
||||||
|
|
||||||
this._readableState.readingMore = true;
|
this._readableState.readingMore = true;
|
||||||
|
|
||||||
@ -160,19 +160,20 @@ IncomingMessage.prototype._read = function _read(n) {
|
|||||||
readStart(this.socket);
|
readStart(this.socket);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// It's possible that the socket will be destroyed, and removed from
|
// It's possible that the socket will be destroyed, and removed from
|
||||||
// any messages, before ever calling this. In that case, just skip
|
// any messages, before ever calling this. In that case, just skip
|
||||||
// it, since something else is destroying this connection anyway.
|
// it, since something else is destroying this connection anyway.
|
||||||
IncomingMessage.prototype.destroy = function destroy(error) {
|
IncomingMessage.prototype._destroy = function _destroy(err, cb) {
|
||||||
// TODO(ronag): Implement in terms of _destroy
|
if (!this.readableEnded || !this.complete) {
|
||||||
this.destroyed = true;
|
this.aborted = true;
|
||||||
if (this.socket)
|
this.emit('aborted');
|
||||||
this.socket.destroy(error);
|
}
|
||||||
return this;
|
if (this.socket && !this.readableEnded) {
|
||||||
|
this.socket.destroy(err);
|
||||||
|
}
|
||||||
|
this.listenerCount('error') > 0 ? cb(err) : cb();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
IncomingMessage.prototype._addHeaderLines = _addHeaderLines;
|
IncomingMessage.prototype._addHeaderLines = _addHeaderLines;
|
||||||
function _addHeaderLines(headers, n) {
|
function _addHeaderLines(headers, n) {
|
||||||
if (headers && headers.length) {
|
if (headers && headers.length) {
|
||||||
|
@ -575,14 +575,7 @@ function socketOnClose(socket, state) {
|
|||||||
function abortIncoming(incoming) {
|
function abortIncoming(incoming) {
|
||||||
while (incoming.length) {
|
while (incoming.length) {
|
||||||
const req = incoming.shift();
|
const req = incoming.shift();
|
||||||
// TODO(ronag): req.destroy(err)
|
req.destroy(connResetException('aborted'));
|
||||||
req.aborted = true;
|
|
||||||
req.destroyed = true;
|
|
||||||
req.emit('aborted');
|
|
||||||
if (req.listenerCount('error') > 0) {
|
|
||||||
req.emit('error', connResetException('aborted'));
|
|
||||||
}
|
|
||||||
req.emit('close');
|
|
||||||
}
|
}
|
||||||
// Abort socket._httpMessage ?
|
// Abort socket._httpMessage ?
|
||||||
}
|
}
|
||||||
@ -741,14 +734,9 @@ function clearIncoming(req) {
|
|||||||
if (parser && parser.incoming === req) {
|
if (parser && parser.incoming === req) {
|
||||||
if (req.readableEnded) {
|
if (req.readableEnded) {
|
||||||
parser.incoming = null;
|
parser.incoming = null;
|
||||||
req.destroyed = true;
|
|
||||||
req.emit('close');
|
|
||||||
} else {
|
} else {
|
||||||
req.on('end', clearIncoming);
|
req.on('end', clearIncoming);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
req.destroyed = true;
|
|
||||||
req.emit('close');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user