From c29b0b00c97afbbb5967c707f18a86cea608a8dd Mon Sep 17 00:00:00 2001 From: SNTL 84 Milan <3goldenlotusroots@gmail.com> Date: Tue, 30 Jun 2026 16:04:41 +0530 Subject: [PATCH 1/2] test: add regression test for issue #1373 default headersTimeout 300s Verifies that undici's fetch does not throw HeadersTimeoutError for a server that responds after 35s, confirming the 300e3ms default is in effect and the old 30s behaviour does not regress. Fixes: nodejs/undici#1373 --- test/issue-1373-default-timeout.js | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 test/issue-1373-default-timeout.js diff --git a/test/issue-1373-default-timeout.js b/test/issue-1373-default-timeout.js new file mode 100644 index 00000000000..5fc4a07694f --- /dev/null +++ b/test/issue-1373-default-timeout.js @@ -0,0 +1,33 @@ +'use strict' + +// Regression test for https://github.com/nodejs/undici/issues/1373 +// Confirms that the default headersTimeout is 300s (not the old 30s), +// so a server that responds after 35s does NOT trigger HeadersTimeoutError. + +const { createServer } = require('node:http') +const { once } = require('node:events') +const { test, after } = require('node:test') +const assert = require('node:assert/strict') +const { fetch } = require('..') + +test('default headersTimeout is 300s — no timeout for 35s slow server (issue #1373)', async (t) => { + const server = createServer((req, res) => { + // Respond after 35 seconds — exceeds old 30s default, within new 300s default + setTimeout(() => { + res.writeHead(200, { 'content-type': 'text/plain' }) + res.end('ok') + }, 35_000) + }) + + server.listen(0) + await once(server, 'listening') + after(() => server.close()) + + const { port } = server.address() + + // This MUST NOT throw HeadersTimeoutError with the 300s default. + // It would have thrown under the old 30s default. + const res = await fetch(`http://localhost:${port}/`) + assert.equal(res.status, 200) + assert.equal(await res.text(), 'ok') +}) From 5292192f8cd069c37bcac2b23191feb6d7a8d96c Mon Sep 17 00:00:00 2001 From: SNTL 84 Milan <3goldenlotusroots@gmail.com> Date: Thu, 2 Jul 2026 16:20:46 +0530 Subject: [PATCH 2/2] test: rewrite issue-1373 regression test with fake timers (no real delay) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per mcollina's review — replace the real 35s setTimeout with mock.timers so CI completes instantly. Fake clock is fast-forwarded past the old 30s default but under the 300s default, confirming no HeadersTimeoutError. Contributed by Milan Soni (SNTL84) · desidevloper.com --- test/issue-1373-default-timeout.js | 53 ++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/test/issue-1373-default-timeout.js b/test/issue-1373-default-timeout.js index 5fc4a07694f..f5ec85c32c4 100644 --- a/test/issue-1373-default-timeout.js +++ b/test/issue-1373-default-timeout.js @@ -1,22 +1,31 @@ 'use strict' // Regression test for https://github.com/nodejs/undici/issues/1373 -// Confirms that the default headersTimeout is 300s (not the old 30s), -// so a server that responds after 35s does NOT trigger HeadersTimeoutError. +// Confirms that the default headersTimeout is 300s (not the old 30s). +// +// Uses fake timers (mock.timers) so the test completes instantly — +// no real 35s wait. The clock is fast-forwarded past the old 30s default +// (to 31s) to confirm no HeadersTimeoutError is raised under the 300s default. const { createServer } = require('node:http') const { once } = require('node:events') -const { test, after } = require('node:test') +const { test, mock, after } = require('node:test') const assert = require('node:assert/strict') -const { fetch } = require('..') +const { Client } = require('..') + +test('default headersTimeout is 300s — no timeout at 31s (issue #1373)', async (t) => { + // Enable fake timers before anything else + mock.timers.enable({ apis: ['setTimeout'] }) + t.after(() => mock.timers.reset()) -test('default headersTimeout is 300s — no timeout for 35s slow server (issue #1373)', async (t) => { const server = createServer((req, res) => { - // Respond after 35 seconds — exceeds old 30s default, within new 300s default - setTimeout(() => { + // Hold the connection open; we'll release it by ticking the fake clock + const timer = setTimeout(() => { res.writeHead(200, { 'content-type': 'text/plain' }) res.end('ok') - }, 35_000) + }, 31_000) // 31s — beyond old 30s default, within 300s default + + req.on('close', () => clearTimeout(timer)) }) server.listen(0) @@ -25,9 +34,27 @@ test('default headersTimeout is 300s — no timeout for 35s slow server (issue # const { port } = server.address() - // This MUST NOT throw HeadersTimeoutError with the 300s default. - // It would have thrown under the old 30s default. - const res = await fetch(`http://localhost:${port}/`) - assert.equal(res.status, 200) - assert.equal(await res.text(), 'ok') + const client = new Client(`http://localhost:${port}`) + t.after(() => client.close()) + + // Start the request (it will hang until the fake clock ticks past 31s) + const responsePromise = new Promise((resolve, reject) => { + client.request({ path: '/', method: 'GET' }, (err, data) => { + if (err) return reject(err) + let body = '' + data.body.on('data', (chunk) => { body += chunk }) + data.body.on('end', () => resolve({ status: data.statusCode, body })) + }) + }) + + // Advance fake clock 31 seconds — triggers the server's setTimeout instantly + mock.timers.tick(31_000) + + // Should resolve without HeadersTimeoutError (would have failed at 30s old default) + const { status, body } = await responsePromise + assert.equal(status, 200) + assert.equal(body, 'ok') }) + +// — Contributed by Milan Soni (SNTL84) · github.com/SNTL84 +// — Open to OSS sponsorship & consulting — AI workflows, automation & full-stack builds · desidevloper.com