From cc213ad7b5ef4cd293abb3e603ab0fbbe5d1dd6b Mon Sep 17 00:00:00 2001 From: Carlos Fuentes Date: Sun, 21 Apr 2024 13:16:08 +0200 Subject: [PATCH] fix(H2-#3140): abort requets upon GOAWAY --- lib/dispatcher/client-h2.js | 6 ++---- lib/dispatcher/client.js | 1 + test/http2.js | 23 ++++++++++++----------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/dispatcher/client-h2.js b/lib/dispatcher/client-h2.js index 7c8ec5f0cf9..cd63bcda2f2 100644 --- a/lib/dispatcher/client-h2.js +++ b/lib/dispatcher/client-h2.js @@ -208,10 +208,9 @@ function onHttp2SessionEnd () { * This is the root cause of #3011 * We need to handle GOAWAY frames properly, and trigger the session close * along with the socket right away - * Find a way to trigger the close cycle from here on. */ function onHTTP2GoAway (code) { - const err = new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${code}`) + const err = new RequestAbortedError(`HTTP/2: "GOAWAY" frame received with code ${code}`) // We need to trigger the close cycle right away // We need to destroy the session and the socket @@ -220,8 +219,7 @@ function onHTTP2GoAway (code) { this[kClient][kOnError](err) this.unref() - // We send the GOAWAY frame response as no error - this.destroy() + util.destroy(this[kSocket], err) } diff --git a/lib/dispatcher/client.js b/lib/dispatcher/client.js index 3b3da96d712..7d6f5fd351f 100644 --- a/lib/dispatcher/client.js +++ b/lib/dispatcher/client.js @@ -376,6 +376,7 @@ function onError (client, err) { assert(client[kPendingIdx] === client[kRunningIdx]) const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { const request = requests[i] util.errorRequest(client, request, err) diff --git a/test/http2.js b/test/http2.js index 5d5badcc0f2..a43700574b8 100644 --- a/test/http2.js +++ b/test/http2.js @@ -234,7 +234,7 @@ test('Should support H2 GOAWAY (server-side)', async t => { server.on('session', session => { setTimeout(() => { - session.goaway(204) + session.goaway(0) }, 1000) }) @@ -274,7 +274,7 @@ test('Should support H2 GOAWAY (server-side)', async t => { t.ok(url instanceof URL) t.deepStrictEqual(disconnectClient, [client]) - t.strictEqual(err.message, 'HTTP/2: "GOAWAY" frame received with code 204') + t.strictEqual(err.message, 'HTTP/2: "GOAWAY" frame received with code 0') }) test('Should throw if bad allowH2 has been passed', async t => { @@ -1427,20 +1427,21 @@ test('#3046 - GOAWAY Frame', async t => { t.strictEqual(err.message, 'HTTP/2: "GOAWAY" frame received with code 0') }) - client.request({ + const response = await client.request({ path: '/', method: 'GET', headers: { 'x-my-header': 'foo' } - }, (err, response) => { - t.ifError(err) - t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') - t.strictEqual(response.headers['x-custom-h2'], 'hello') - t.strictEqual(response.statusCode, 200) - // We stop the sent the GOAWAY frame before the body is sent, as we received the GOAWAY frame - // before the DATA one, the body will be empty - response.body.dump() + }) + + t.strictEqual(response.headers['content-type'], 'text/plain; charset=utf-8') + t.strictEqual(response.headers['x-custom-h2'], 'hello') + t.strictEqual(response.statusCode, 200) + + t.rejects(response.body.text.bind(response.body), { + message: 'HTTP/2: "GOAWAY" frame received with code 0', + code: 'UND_ERR_ABORTED' }) await t.completed