From 7ae20e6070fa7de2831a907c92fa44268003c145 Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Sun, 7 Apr 2024 14:08:08 +0200 Subject: [PATCH] fix: bad client destroy on servername change (#3066) --- lib/dispatcher/client.js | 5 +- test/node-test/client-dispatch.js | 89 +++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/lib/dispatcher/client.js b/lib/dispatcher/client.js index a8be043a92f..054198f65c4 100644 --- a/lib/dispatcher/client.js +++ b/lib/dispatcher/client.js @@ -581,7 +581,10 @@ function _resume (client, sync) { } client[kServerName] = request.servername - client[kHTTPContext]?.destroy(new InformationalError('servername changed')) + client[kHTTPContext]?.destroy(new InformationalError('servername changed'), () => { + client[kHTTPContext] = null + resume(client) + }) } if (client[kConnecting]) { diff --git a/test/node-test/client-dispatch.js b/test/node-test/client-dispatch.js index d780da3b7b9..55713d9ad0e 100644 --- a/test/node-test/client-dispatch.js +++ b/test/node-test/client-dispatch.js @@ -3,6 +3,7 @@ const { test } = require('node:test') const assert = require('node:assert/strict') const http = require('node:http') +const https = require('node:https') const { Client, Pool, errors } = require('../..') const stream = require('node:stream') const { createSecureServer } = require('node:http2') @@ -959,3 +960,91 @@ test('dispatches in expected order for http2', async (t) => { await p.completed }) + +test('Issue#3065 - fix bad destroy handling', async (t) => { + const p = tspl(t, { plan: 4 }) + const server = https.createServer(pem, (req, res) => { + res.writeHead(200, { 'content-type': 'text/plain' }) + res.end('ended') + }) + + server.listen(0, () => { + const client = new Client(`https://localhost:${server.address().port}`, { + connect: { + rejectUnauthorized: false + } + }) + + t.after(closeClientAndServerAsPromise(client, server)) + + const dispatches = [] + const dispatches2 = [] + + client.once('disconnect', (...args) => { + const [,, err] = args + p.strictEqual(err.code, 'UND_ERR_INFO') + p.strictEqual(err.message, 'servername changed') + }) + + client.dispatch({ + path: '/', + method: 'POST', + body: 'body' + }, { + onConnect () { + dispatches.push('onConnect') + }, + onBodySent () { + dispatches.push('onBodySent') + }, + onResponseStarted () { + dispatches.push('onResponseStarted') + }, + onHeaders () { + dispatches.push('onHeaders') + }, + onData () { + dispatches.push('onData') + }, + onComplete () { + dispatches.push('onComplete') + p.deepStrictEqual(dispatches, ['onConnect', 'onBodySent', 'onResponseStarted', 'onHeaders', 'onData', 'onComplete']) + }, + onError (err) { + p.ifError(err) + } + }) + + client.dispatch({ + servername: 'google.com', + path: '/', + method: 'POST', + body: 'body' + }, { + onConnect () { + dispatches2.push('onConnect') + }, + onBodySent () { + dispatches2.push('onBodySent') + }, + onResponseStarted () { + dispatches2.push('onResponseStarted') + }, + onHeaders () { + dispatches2.push('onHeaders') + }, + onData () { + dispatches2.push('onData') + }, + onComplete () { + dispatches2.push('onComplete') + p.deepStrictEqual(dispatches2, ['onConnect', 'onBodySent', 'onResponseStarted', 'onHeaders', 'onData', 'onComplete']) + }, + onError (err) { + p.ifError(err) + } + }) + }) + + await p.completed +})