Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion lib/_http_outgoing.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,14 +287,20 @@ OutgoingMessage.prototype.uncork = function uncork() {
callbacks.push(buf[n + 2]);
}
}
this._send(crlf_buf, null, callbacks.length ? (err) => {
const ret = this._send(crlf_buf, null, callbacks.length ? (err) => {
for (const callback of callbacks) {
callback(err);
}
} : null);

this[kChunkedBuffer].length = 0;
this[kChunkedLength] = 0;

// If we successfully flushed and had pending drain, emit it
if (ret && this[kNeedDrain]) {
this[kNeedDrain] = false;
this.emit('drain');
}
};

OutgoingMessage.prototype.setTimeout = function setTimeout(msecs, callback) {
Expand Down
70 changes: 70 additions & 0 deletions test/parallel/test-http-response-drain-cork.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'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(100)), true);

// Write large amount that should require drain
const needsDrain = !res.write('2'.repeat(1000000));

if (needsDrain) {
// 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 if needed
res.uncork();

await drainPromise;

// Cork again for next write
res.cork();
}

// Write more data
res.write('3'.repeat(100));

// Final uncork and end
res.uncork();
res.end();
}));

server.listen(0, common.mustCall(() => {
http.get({
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, 100 + 1000000 + 100);
assert.strictEqual(data.substring(0, 100), '1'.repeat(100));
assert.strictEqual(data.substring(100, 1000100), '2'.repeat(1000000));
assert.strictEqual(data.substring(1000100), '3'.repeat(100));

server.close();
}));
}));
}));