From aa7243e3d447058f351a05af70e9ff111562cec5 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Sun, 10 Jan 2021 11:25:31 +0100 Subject: [PATCH] http: refactor ClientRequest destroy PR-URL: https://github.com/nodejs/node/pull/36863 Reviewed-By: Benjamin Gruenbaum --- lib/_http_client.js | 59 ++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/lib/_http_client.js b/lib/_http_client.js index becd6e7cce3dd9..8b9af5391c64e1 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -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'); } @@ -830,11 +804,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();