Files
node/test/parallel/test-http-response-drain-cork.js
David Evans 615749b9b5 http: fix drain event with cork/uncork
When using cork() and uncork() with ServerResponse, the drain
event was not reliably emitted after uncorking. This occurred
because the uncork() method did not check if a drain was pending
(kNeedDrain flag) after flushing the chunked buffer.

This fix ensures that when uncork() successfully flushes buffered
data and a drain was needed, the drain event is emitted
immediately.

This commit is a copy of PR #60437 (abandoned) with minor linting
fixes.

Fixes: https://github.com/nodejs/node/issues/60432
Signed-off-by: David Evans <davidje13@users.noreply.github.com>
PR-URL: https://github.com/nodejs/node/pull/64038
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
2026-07-02 15:28:39 +00:00

65 lines
1.8 KiB
JavaScript

'use strict';
const common = require('../common');
const http = require('http');
const assert = require('assert');
// Test that drain event is emitted correctly when using cork/uncork
// with ServerResponse and the write buffer is full
const server = http.createServer(common.mustCall(async (req, res) => {
res.cork();
// Write small amount - won't need drain
assert.strictEqual(res.write('1'.repeat(10)), true);
// Write enough to exceed highWaterMark (set in 'connection' listener)
assert.strictEqual(res.write('2'.repeat(1000)), false);
// Verify writableNeedDrain is set
assert.strictEqual(res.writableNeedDrain, true);
// Wait for drain event after uncorking
const drainPromise = new Promise((resolve) => {
res.once('drain', common.mustCall(() => {
// After drain, writableNeedDrain should be false
assert.strictEqual(res.writableNeedDrain, false);
resolve();
}));
});
// Uncork should trigger drain
res.uncork();
await drainPromise;
res.end();
}));
server.on('connection', common.mustCall((socket) => {
// Set high water mark large enough to cover HTTP overhead + first
// small content batch, but not enough to cover second batch.
socket._writableState.highWaterMark = 1000;
}));
server.listen(0, common.localhostIPv4, common.mustCall(() => {
http.get({
host: common.localhostIPv4,
port: server.address().port,
}, common.mustCall((res) => {
let data = '';
res.setEncoding('utf8');
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', common.mustCall(() => {
// Verify we got all the data
assert.strictEqual(data.length, 10 + 1000);
assert.strictEqual(data.substring(0, 10), '1'.repeat(10));
assert.strictEqual(data.substring(10), '2'.repeat(1000));
server.close(common.mustCall());
}));
}));
}));