http: end with data can cause write after end
Calling end() with data while ending should trigger a write after end error. PR-URL: https://github.com/nodejs/node/pull/28666 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
parent
a7c523e26d
commit
c776a37791
@ -641,17 +641,20 @@ OutgoingMessage.prototype.write = function write(chunk, encoding, callback) {
|
||||
return ret;
|
||||
};
|
||||
|
||||
function writeAfterEnd(msg, callback) {
|
||||
const err = new ERR_STREAM_WRITE_AFTER_END();
|
||||
const triggerAsyncId = msg.socket ? msg.socket[async_id_symbol] : undefined;
|
||||
defaultTriggerAsyncIdScope(triggerAsyncId,
|
||||
process.nextTick,
|
||||
writeAfterEndNT,
|
||||
msg,
|
||||
err,
|
||||
callback);
|
||||
}
|
||||
|
||||
function write_(msg, chunk, encoding, callback, fromEnd) {
|
||||
if (msg.finished) {
|
||||
const err = new ERR_STREAM_WRITE_AFTER_END();
|
||||
const triggerAsyncId = msg.socket ? msg.socket[async_id_symbol] : undefined;
|
||||
defaultTriggerAsyncIdScope(triggerAsyncId,
|
||||
process.nextTick,
|
||||
writeAfterEndNT,
|
||||
msg,
|
||||
err,
|
||||
callback);
|
||||
|
||||
writeAfterEnd(msg, callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -748,17 +751,6 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
|
||||
encoding = null;
|
||||
}
|
||||
|
||||
if (this.finished) {
|
||||
if (typeof callback === 'function') {
|
||||
if (!this.writableFinished) {
|
||||
this.on('finish', callback);
|
||||
} else {
|
||||
callback(new ERR_STREAM_ALREADY_FINISHED('end'));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
if (this.socket) {
|
||||
this.socket.cork();
|
||||
}
|
||||
@ -767,6 +759,12 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
|
||||
if (typeof chunk !== 'string' && !(chunk instanceof Buffer)) {
|
||||
throw new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk);
|
||||
}
|
||||
|
||||
if (this.finished) {
|
||||
writeAfterEnd(this, callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
if (!this._header) {
|
||||
if (typeof chunk === 'string')
|
||||
this._contentLength = Buffer.byteLength(chunk, encoding);
|
||||
@ -774,6 +772,15 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
|
||||
this._contentLength = chunk.length;
|
||||
}
|
||||
write_(this, chunk, encoding, null, true);
|
||||
} else if (this.finished) {
|
||||
if (typeof callback === 'function') {
|
||||
if (!this.writableFinished) {
|
||||
this.on('finish', callback);
|
||||
} else {
|
||||
callback(new ERR_STREAM_ALREADY_FINISHED('end'));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
} else if (!this._header) {
|
||||
this._contentLength = 0;
|
||||
this._implicitHeader();
|
||||
|
27
test/parallel/test-http-server-write-end-after-end.js
Normal file
27
test/parallel/test-http-server-write-end-after-end.js
Normal file
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const http = require('http');
|
||||
|
||||
const server = http.createServer(handle);
|
||||
|
||||
function handle(req, res) {
|
||||
res.on('error', common.mustCall((err) => {
|
||||
common.expectsError({
|
||||
code: 'ERR_STREAM_WRITE_AFTER_END',
|
||||
name: 'Error'
|
||||
})(err);
|
||||
server.close();
|
||||
}));
|
||||
|
||||
res.write('hello');
|
||||
res.end();
|
||||
|
||||
setImmediate(common.mustCall(() => {
|
||||
res.end('world');
|
||||
}));
|
||||
}
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
http.get(`http://localhost:${server.address().port}`);
|
||||
}));
|
Loading…
x
Reference in New Issue
Block a user