Skip to content

Commit d2a920c

Browse files
committed
http: don't throw on Uint8Arrays for http.ServerResponse#write
Don't throw errors on Uint8Arrays and added test for all valid types. Backport-PR-URL: nodejs#33488 PR-URL: nodejs#33155 Fixes: nodejs#33379 Refs: nodejs#29829 Reviewed-By: Robert Nagy <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Zeyu Yang <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent daf1d84 commit d2a920c

File tree

3 files changed

+53
-8
lines changed

3 files changed

+53
-8
lines changed

lib/_http_outgoing.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,13 @@ const {
5555
ERR_INVALID_CHAR,
5656
ERR_METHOD_NOT_IMPLEMENTED,
5757
ERR_STREAM_CANNOT_PIPE,
58+
ERR_STREAM_NULL_VALUES,
5859
ERR_STREAM_WRITE_AFTER_END
5960
},
6061
hideStackFrames
6162
} = require('internal/errors');
6263
const { validateString } = require('internal/validators');
64+
const { isUint8Array } = require('internal/util/types');
6365

6466
const HIGH_WATER_MARK = getDefaultHighWaterMark();
6567
const { CRLF, debug } = common;
@@ -625,6 +627,16 @@ OutgoingMessage.prototype.write = function write(chunk, encoding, callback) {
625627
};
626628

627629
function write_(msg, chunk, encoding, callback, fromEnd) {
630+
if (typeof callback !== 'function')
631+
callback = function() {};
632+
633+
if (chunk === null)
634+
throw new ERR_STREAM_NULL_VALUES();
635+
636+
if (typeof chunk !== 'string' && !isUint8Array(chunk))
637+
throw new ERR_INVALID_ARG_TYPE(
638+
'chunk', ['string', 'Buffer', 'Uint8Array'], chunk);
639+
628640
if (msg.finished) {
629641
const err = new ERR_STREAM_WRITE_AFTER_END();
630642
const triggerAsyncId = msg.socket ? msg.socket[async_id_symbol] : undefined;
@@ -649,9 +661,9 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
649661
return true;
650662
}
651663

652-
if (!fromEnd && typeof chunk !== 'string' && !(chunk instanceof Buffer)) {
664+
if (!fromEnd && typeof chunk !== 'string' && !isUint8Array(chunk)) {
653665
throw new ERR_INVALID_ARG_TYPE('first argument',
654-
['string', 'Buffer'], chunk);
666+
['string', 'Buffer', 'Uint8Array'], chunk);
655667
}
656668

657669
if (!fromEnd && msg.connection && !msg.connection.writableCorked) {
@@ -742,7 +754,8 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
742754

743755
if (chunk) {
744756
if (typeof chunk !== 'string' && !(chunk instanceof Buffer)) {
745-
throw new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk);
757+
throw new ERR_INVALID_ARG_TYPE(
758+
'chunk', ['string', 'Buffer', 'Uint8Array'], chunk);
746759
}
747760
if (!this._header) {
748761
if (typeof chunk === 'string')

test/parallel/test-http-outgoing-proto.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,24 @@ assert.throws(() => {
7171
outgoingMessage.write('');
7272
}
7373

74-
assert(OutgoingMessage.prototype.write.call({ _header: 'test' }));
74+
assert.throws(() => {
75+
const outgoingMessage = new OutgoingMessage();
76+
outgoingMessage.write.call({ _header: 'test' });
77+
}, {
78+
code: 'ERR_INVALID_ARG_TYPE',
79+
name: 'TypeError',
80+
message: 'The "chunk" argument must be of type string or an instance of ' +
81+
'Buffer or Uint8Array. Received undefined'
82+
});
7583

7684
assert.throws(() => {
7785
const outgoingMessage = new OutgoingMessage();
7886
outgoingMessage.write.call({ _header: 'test', _hasBody: 'test' });
7987
}, {
8088
code: 'ERR_INVALID_ARG_TYPE',
8189
name: 'TypeError',
82-
message: 'The first argument must be of type string or an instance of ' +
83-
'Buffer. Received undefined'
90+
message: 'The "chunk" argument must be of type string or an instance of ' +
91+
'Buffer or Uint8Array. Received undefined'
8492
});
8593

8694
assert.throws(() => {
@@ -89,8 +97,8 @@ assert.throws(() => {
8997
}, {
9098
code: 'ERR_INVALID_ARG_TYPE',
9199
name: 'TypeError',
92-
message: 'The first argument must be of type string or an instance of ' +
93-
'Buffer. Received type number (1)'
100+
message: 'The "chunk" argument must be of type string or an instance of ' +
101+
'Buffer or Uint8Array. Received type number (1)'
94102
});
95103

96104
// addTrailers()
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const http = require('http');
5+
6+
const httpServer = http.createServer(common.mustCall(function(req, res) {
7+
httpServer.close();
8+
assert.throws(() => {
9+
res.write(['Throws.']);
10+
}, {
11+
code: 'ERR_INVALID_ARG_TYPE'
12+
});
13+
// should not throw
14+
res.write('1a2b3c');
15+
// should not throw
16+
res.write(new Uint8Array(1024));
17+
// should not throw
18+
res.write(Buffer.from('1'.repeat(1024)));
19+
res.end();
20+
}));
21+
22+
httpServer.listen(0, common.mustCall(function() {
23+
http.get({ port: this.address().port });
24+
}));

0 commit comments

Comments
 (0)