http: refactor ClientRequest destroy

PR-URL: https://github.com/nodejs/node/pull/36863
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit is contained in:
Robert Nagy 2021-01-10 11:25:31 +01:00
parent 963dec304d
commit e39a3f86bf
1 changed files with 26 additions and 33 deletions

View File

@ -77,7 +77,7 @@ const {
DTRACE_HTTP_CLIENT_RESPONSE
} = require('internal/dtrace');
const { addAbortSignal } = require('stream');
const { addAbortSignal, finished } = require('stream');
const INVALID_PATH_REGEX = /[^\u0021-\u00ff]/;
const kError = Symbol('kError');
@ -370,38 +370,12 @@ ClientRequest.prototype.destroy = function destroy(err) {
this.res._dump();
}
// In the event that we don't have a socket, we will pop out of
// the request queue through handling in onSocket.
if (this.socket) {
_destroy(this, this.socket, err);
} else if (err) {
this[kError] = err;
}
this[kError] = err;
this.socket?.destroy(err);
return this;
};
function _destroy(req, socket, err) {
// TODO (ronag): Check if socket was used at all (e.g. headersSent) and
// re-use it in that case. `req.socket` just checks whether the socket was
// assigned to the request and *might* have been used.
if (socket && (!req.agent || req.socket)) {
socket.destroy(err);
} else {
if (socket) {
socket.emit('free');
}
if (!req.aborted && !err) {
err = connResetException('socket hang up');
}
if (err) {
req.emit('error', err);
}
req._closed = true;
req.emit('close');
}
}
function emitAbortNT(req) {
req.emit('abort');
}
@ -813,11 +787,30 @@ ClientRequest.prototype.onSocket = function onSocket(socket, err) {
};
function onSocketNT(req, socket, err) {
if (req.destroyed) {
_destroy(req, socket, req[kError]);
} else if (err) {
if (req.destroyed || err) {
req.destroyed = true;
_destroy(req, null, err);
function _destroy(req, err) {
if (!req.aborted && !err) {
err = connResetException('socket hang up');
}
if (err) {
req.emit('error', err);
}
req._closed = true;
req.emit('close');
}
if (!err && req.agent) {
socket?.emit('free');
} else if (socket) {
finished(socket.destroy(err || req[kError]), (er) => {
_destroy(req, er || err);
});
return;
}
_destroy(req, err || req[kError]);
} else {
tickOnSocket(req, socket);
req._flush();