From 9b4bb3a6cab1cacc4b2505da3d94fbd557ee695a Mon Sep 17 00:00:00 2001 From: Ryan <44614514+YarnSaw@users.noreply.github.com> Date: Mon, 26 Oct 2026 11:17:11 -0400 Subject: [PATCH 1/2] Ensure request is defined in error handler --- lib/XMLHttpRequest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/XMLHttpRequest.js b/lib/XMLHttpRequest.js index f37edf02..f841b770 100644 --- a/lib/XMLHttpRequest.js +++ b/lib/XMLHttpRequest.js @@ -862,7 +862,7 @@ function XMLHttpRequest(opts) { var errorHandler = function(error) { // In the case of https://nodejs.org/api/http.html#requestreusedsocket triggering an ECONNRESET, // don't fail the xhr request, attempt again. - if (request.reusedSocket && error.code === 'ECONNRESET') + if (request && request.reusedSocket && error.code === 'ECONNRESET') return doRequest(options, responseHandler).on('error', errorHandler); handleError(error); } From 6ce3d19d2fa7e3f9205cf9258b82943e1e41b940 Mon Sep 17 00:00:00 2001 From: Ryan Saweczko Date: Thu, 29 Oct 2026 16:36:44 -0400 Subject: [PATCH 2/2] Associate error handler with specific request --- lib/XMLHttpRequest.js | 12 ++++++++---- tests/abort-request.js | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 tests/abort-request.js diff --git a/lib/XMLHttpRequest.js b/lib/XMLHttpRequest.js index f841b770..45525f8a 100644 --- a/lib/XMLHttpRequest.js +++ b/lib/XMLHttpRequest.js @@ -859,11 +859,14 @@ function XMLHttpRequest(opts) { } // Error handler for the request - var errorHandler = function(error) { + var errorHandler = function(error, associatedRequest) { // In the case of https://nodejs.org/api/http.html#requestreusedsocket triggering an ECONNRESET, // don't fail the xhr request, attempt again. - if (request && request.reusedSocket && error.code === 'ECONNRESET') - return doRequest(options, responseHandler).on('error', errorHandler); + if (associatedRequest.reusedSocket && error.code === 'ECONNRESET') + { + const retryRequest = doRequest(options, responseHandler) + retryRequest.on('error', (error) => errorHandler(error, retryRequest)); + } handleError(error); } @@ -871,7 +874,8 @@ function XMLHttpRequest(opts) { opt = Object.assign(Object.create(null), opt); if (isSsl) Object.assign(opt, sslOptions); - request = doRequest(opt, responseHandler).on('error', errorHandler); + const httpRequest = doRequest(opt, responseHandler); + request = httpRequest.on('error', (error) => errorHandler(error, httpRequest)); if (opts.autoUnref) { request.on('socket', function (socket) { diff --git a/tests/abort-request.js b/tests/abort-request.js new file mode 100644 index 00000000..634e08fb --- /dev/null +++ b/tests/abort-request.js @@ -0,0 +1,41 @@ +'use strict'; + +const http = require('http'); +const XHR = require('../lib/XMLHttpRequest').XMLHttpRequest; + +process.on('uncaughtException', (e) => { console.error('uncaught: ', e); process.exitCode = 1; }); +process.on('unhandledRejection', (e) => { console.error('unhandled: ', e); process.exitCode = 2; }); + +const server = http.createServer((req, res) => { + // never respond to requests - simulate slow server for the abort +}); + +server.listen(0, '127.0.0.1', () => { + requestAndAbort(); +}); + +function requestAndAbort() { + const url = new URL(`http://127.0.0.1:${server.address().port}`); + const xhr = new XHR(); + + xhr.open('GET', url); + xhr.send(); + + setTimeout(() => { + console.log('calling abort'); + try { + xhr.abort() + } + catch (e) { + console.error('abort threw:', e); + process.exitCode = 3; + } + console.log('aborted request') + setTimeout(() => { + server.close(); + server.closeAllConnections?.(); + process.exit(); + }, 500); + + }, 200); +} \ No newline at end of file