From bee7a72930548f010319f29f50f179a0c1da9c54 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 --- 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 b81ffa1cefc573..24a02cf1c7b1c4 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -76,7 +76,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'); @@ -376,38 +376,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'); } @@ -819,11 +793,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); }