From 06a8208c477633050e9bad368a5533065c34d402 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Sun, 14 Jul 2019 21:16:52 +0200 Subject: [PATCH 1/3] http: clientRequest.abort is destroy --- doc/api/deprecations.md | 17 +++++++++++++++ doc/api/http.md | 4 ++++ lib/_http_client.js | 21 +++++++++++++------ test/parallel/test-http-client-close-event.js | 4 +++- test/parallel/test-http-client-set-timeout.js | 4 +++- 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 0d97cd38df0673..db44cb3ee08214 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -2500,6 +2500,21 @@ Type: Runtime Passing a callback to [`worker.terminate()`][] is deprecated. Use the returned `Promise` instead, or a listener to the worker’s `'exit'` event. + +### DEP0XXX: ClientRequest.abort() is destroy + + +Type: Documentation-only + +`[ClientRequest.destroy()`][] should be the same as +`[ClientRequest.abort()`][]. Make ClientRequest more streamlike by deprecating + abort(). + [`--http-parser=legacy`]: cli.html#cli_http_parser_library [`--pending-deprecation`]: cli.html#cli_pending_deprecation [`--throw-deprecation`]: cli.html#cli_throw_deprecation @@ -2508,6 +2523,8 @@ Passing a callback to [`worker.terminate()`][] is deprecated. Use the returned [`Buffer.from(buffer)`]: buffer.html#buffer_class_method_buffer_from_buffer [`Buffer.isBuffer()`]: buffer.html#buffer_class_method_buffer_isbuffer_obj [`Cipher`]: crypto.html#crypto_class_cipher +[`ClientRequest.abort()`]: #http.html#http_request_abort +[`ClientRequest.destroy()`]: #stream.html#stream_readable_destroy_error [`Decipher`]: crypto.html#crypto_class_decipher [`EventEmitter.listenerCount(emitter, eventName)`]: events.html#events_eventemitter_listenercount_emitter_eventname [`REPLServer.clearBufferedCommand()`]: repl.html#repl_replserver_clearbufferedcommand diff --git a/doc/api/http.md b/doc/api/http.md index 4923b6a61d840f..89d41201cd068f 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -546,8 +546,11 @@ srv.listen(1337, '127.0.0.1', () => { ### request.abort() +> Stability: 0 - Deprecated: Use [`request.destroy()`][] instead. + Marks the request as aborting. Calling this will cause remaining data in the response to be dropped and the socket to be destroyed. @@ -2215,6 +2218,7 @@ not abort the request or do anything besides add a `'timeout'` event. [`net.createConnection()`]: net.html#net_net_createconnection_options_connectlistener [`new URL()`]: url.html#url_constructor_new_url_input_base [`removeHeader(name)`]: #http_request_removeheader_name +[`request.destroy()`]: #stream.html#stream_readable_destroy_error [`request.end()`]: #http_request_end_data_encoding_callback [`request.flushHeaders()`]: #http_request_flushheaders [`request.getHeader()`]: #http_request_getheader_name diff --git a/lib/_http_client.js b/lib/_http_client.js index 14d9e59f63634f..7a80ce88dff394 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -311,11 +311,13 @@ ClientRequest.prototype._implicitHeader = function _implicitHeader() { this[outHeadersKey]); }; -ClientRequest.prototype.abort = function abort() { - if (!this.aborted) { - process.nextTick(emitAbortNT.bind(this)); +ClientRequest.prototype.destroy = function destroy(error) { + if (this.aborted) { + return; } + this.aborted = true; + process.nextTick(emitAbortNT.bind(this)); // If we're aborting, we don't care about any more response data. if (this.res) { @@ -326,10 +328,14 @@ ClientRequest.prototype.abort = function abort() { // the request queue through handling in onSocket. if (this.socket) { // in-progress - this.socket.destroy(); + this.socket.destroy(error); + } else { + this._destroyError = error; } }; - +ClientRequest.prototype.abort = function abort() { + this.destroy(); +}; function emitAbortNT() { this.emit('abort'); @@ -708,8 +714,11 @@ function onSocketNT(req, socket) { if (req.aborted) { // If we were aborted while waiting for a socket, skip the whole thing. if (!req.agent) { - socket.destroy(); + socket.destroy(req._destroyError); } else { + if (req._destroyError) { + req.emit('error', req._destroyError); + } socket.emit('free'); } } else { diff --git a/test/parallel/test-http-client-close-event.js b/test/parallel/test-http-client-close-event.js index 7573931ac48ef6..4bd0832e4cfb6f 100644 --- a/test/parallel/test-http-client-close-event.js +++ b/test/parallel/test-http-client-close-event.js @@ -26,5 +26,7 @@ server.listen(0, common.mustCall(() => { server.close(); })); - req.destroy(); + const err = new Error('socket hang up'); + err.code = 'ECONNRESET'; + req.destroy(err); })); diff --git a/test/parallel/test-http-client-set-timeout.js b/test/parallel/test-http-client-set-timeout.js index 15aae7023bf3f1..9d267de6ac8dca 100644 --- a/test/parallel/test-http-client-set-timeout.js +++ b/test/parallel/test-http-client-set-timeout.js @@ -43,6 +43,8 @@ server.listen(0, mustCall(() => { req.on('timeout', mustCall(() => { strictEqual(req.socket.listenerCount('timeout'), 0); - req.destroy(); + const err = new Error('socket hang up'); + err.code = 'ECONNRESET'; + req.destroy(err); })); })); From dfcaf1848cd4fc104cb809d5595907e2e4b00e58 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Fri, 7 Jun 2019 14:20:43 +0200 Subject: [PATCH 2/3] http: fix test where aborted should not be emitted --- doc/api/http.md | 5 ++-- lib/_http_client.js | 16 +++++++++---- test/parallel/test-http-client-aborted.js | 23 +++++++++++++++++++ ...test-http-client-no-error-after-aborted.js | 21 +++++++++++++++++ .../test-http-client-timeout-on-connect.js | 3 +-- .../test-http-writable-true-after-close.js | 2 +- 6 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 test/parallel/test-http-client-aborted.js create mode 100644 test/parallel/test-http-client-no-error-after-aborted.js diff --git a/doc/api/http.md b/doc/api/http.md index 89d41201cd068f..172b63c23ea210 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -552,7 +552,8 @@ deprecated: REPLACEME > Stability: 0 - Deprecated: Use [`request.destroy()`][] instead. Marks the request as aborting. Calling this will cause remaining data -in the response to be dropped and the socket to be destroyed. +in the response to be dropped and the socket to be destroyed. After +calling this method no further errors will be emitted. ### request.aborted