| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 9582c8e commit 3538521
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -25,7 +25,6 @@ const { | |||
| 25 | 25 | Array, | |
| 26 | 26 | ArrayIsArray, | |
| 27 | 27 | ArrayPrototypeJoin, | |
| 28 | - MathAbs, | ||
| 29 | 28 | MathFloor, | |
| 30 | 29 | NumberPrototypeToString, | |
| 31 | 30 | ObjectCreate, | |
@@ -87,7 +86,6 @@ const HIGH_WATER_MARK = getDefaultHighWaterMark(); | |||
| 87 | 86 | const kCorked = Symbol('corked'); | |
| 88 | 87 | const kUniqueHeaders = Symbol('kUniqueHeaders'); | |
| 89 | 88 | const kBytesWritten = Symbol('kBytesWritten'); | |
| 90 | - const kEndCalled = Symbol('kEndCalled'); | ||
| 91 | 89 | const kErrored = Symbol('errored'); | |
| 92 | 90 | ||
| 93 | 91 | const nop = () => {}; | |
@@ -134,7 +132,6 @@ function OutgoingMessage() { | |||
| 134 | 132 | ||
| 135 | 133 | this.strictContentLength = false; | |
| 136 | 134 | this[kBytesWritten] = 0; | |
| 137 | - this[kEndCalled] = false; | ||
| 138 | 135 | this._contentLength = null; | |
| 139 | 136 | this._hasBody = true; | |
| 140 | 137 | this._trailer = ''; | |
@@ -356,7 +353,7 @@ OutgoingMessage.prototype.destroy = function destroy(error) { | |||
| 356 | 353 | ||
| 357 | 354 | ||
| 358 | 355 | // This abstract either writing directly to the socket or buffering it. | |
| 359 | - OutgoingMessage.prototype._send = function _send(data, encoding, callback) { | ||
| 356 | + OutgoingMessage.prototype._send = function _send(data, encoding, callback, byteLength) { | ||
| 360 | 357 | // This is a shameful hack to get the headers and first body chunk onto | |
| 361 | 358 | // the same packet. Future versions of Node are going to take care of | |
| 362 | 359 | // this at a lower level and in a more general way. | |
@@ -378,20 +375,11 @@ OutgoingMessage.prototype._send = function _send(data, encoding, callback) { | |||
| 378 | 375 | } | |
| 379 | 376 | this._headerSent = true; | |
| 380 | 377 | } | |
| 381 | - return this._writeRaw(data, encoding, callback); | ||
| 378 | + return this._writeRaw(data, encoding, callback, byteLength); | ||
| 382 | 379 | }; | |
| 383 | 380 | ||
| 384 | - function _getMessageBodySize(chunk, headers, encoding) { | ||
| 385 | - if (Buffer.isBuffer(chunk)) return chunk.length; | ||
| 386 | - const chunkLength = chunk ? Buffer.byteLength(chunk, encoding) : 0; | ||
| 387 | - const headerLength = headers ? headers.length : 0; | ||
| 388 | - if (headerLength === chunkLength) return 0; | ||
| 389 | - if (headerLength < chunkLength) return MathAbs(chunkLength - headerLength); | ||
| 390 | - return chunkLength; | ||
| 391 | - } | ||
| 392 | - | ||
| 393 | 381 | OutgoingMessage.prototype._writeRaw = _writeRaw; | |
| 394 | - function _writeRaw(data, encoding, callback) { | ||
| 382 | + function _writeRaw(data, encoding, callback, size) { | ||
| 395 | 383 | const conn = this.socket; | |
| 396 | 384 | if (conn && conn.destroyed) { | |
| 397 | 385 | // The socket was destroyed. If we're still trying to write to it, | |
@@ -404,25 +392,6 @@ function _writeRaw(data, encoding, callback) { | |||
| 404 | 392 | encoding = null; | |
| 405 | 393 | } | |
| 406 | 394 | ||
| 407 | - // TODO(sidwebworks): flip the `strictContentLength` default to `true` in a future PR | ||
| 408 | - if (this.strictContentLength && conn && conn.writable && !this._removedContLen && this._hasBody) { | ||
| 409 | - const skip = conn._httpMessage.statusCode === 304 || (this.hasHeader('transfer-encoding') || this.chunkedEncoding); | ||
| 410 | - | ||
| 411 | - if (typeof this._contentLength === 'number' && !skip) { | ||
| 412 | - const size = _getMessageBodySize(data, conn._httpMessage._header, encoding); | ||
| 413 | - | ||
| 414 | - if ((size + this[kBytesWritten]) > this._contentLength) { | ||
| 415 | - throw new ERR_HTTP_CONTENT_LENGTH_MISMATCH(size + this[kBytesWritten], this._contentLength); | ||
| 416 | - } | ||
| 417 | - | ||
| 418 | - if (this[kEndCalled] && (size + this[kBytesWritten]) !== this._contentLength) { | ||
| 419 | - throw new ERR_HTTP_CONTENT_LENGTH_MISMATCH(size + this[kBytesWritten], this._contentLength); | ||
| 420 | - } | ||
| 421 | - | ||
| 422 | - this[kBytesWritten] += size; | ||
| 423 | - } | ||
| 424 | - } | ||
| 425 | - | ||
| 426 | 395 | if (conn && conn._httpMessage === this && conn.writable) { | |
| 427 | 396 | // There might be pending data in the this.output buffer. | |
| 428 | 397 | if (this.outputData.length) { | |
@@ -882,18 +851,24 @@ function emitErrorNt(msg, err, callback) { | |||
| 882 | 851 | } | |
| 883 | 852 | } | |
| 884 | 853 | ||
| 854 | + function strictContentLength(msg) { | ||
| 855 | + return ( | ||
| 856 | + msg.strictContentLength && | ||
| 857 | + msg._contentLength != null && | ||
| 858 | + msg._hasBody && | ||
| 859 | + !msg._removedContLen && | ||
| 860 | + !msg.chunkedEncoding && | ||
| 861 | + !msg.hasHeader('transfer-encoding') | ||
| 862 | + ); | ||
| 863 | + } | ||
| 864 | + | ||
| 885 | 865 | function write_(msg, chunk, encoding, callback, fromEnd) { | |
| 886 | 866 | if (typeof callback !== 'function') | |
| 887 | 867 | callback = nop; | |
| 888 | 868 | ||
| 889 | - let len; | ||
| 890 | 869 | if (chunk === null) { | |
| 891 | 870 | throw new ERR_STREAM_NULL_VALUES(); | |
| 892 | - } else if (typeof chunk === 'string') { | ||
| 893 | - len = Buffer.byteLength(chunk, encoding); | ||
| 894 | - } else if (isUint8Array(chunk)) { | ||
| 895 | - len = chunk.length; | ||
| 896 | - } else { | ||
| 871 | + } else if (typeof chunk !== 'string' && !isUint8Array(chunk)) { | ||
| 897 | 872 | throw new ERR_INVALID_ARG_TYPE( | |
| 898 | 873 | 'chunk', ['string', 'Buffer', 'Uint8Array'], chunk); | |
| 899 | 874 | } | |
@@ -914,8 +889,24 @@ function write_(msg, chunk, encoding, callback, fromEnd) { | |||
| 914 | 889 | return false; | |
| 915 | 890 | } | |
| 916 | 891 | ||
| 892 | + let len; | ||
| 893 | + | ||
| 894 | + if (msg.strictContentLength) { | ||
| 895 | + len ??= typeof chunk === 'string' ? Buffer.byteLength(chunk, encoding) : chunk.byteLength; | ||
| 896 | + | ||
| 897 | + if ( | ||
| 898 | + strictContentLength(msg) && | ||
| 899 | + (fromEnd ? msg[kBytesWritten] + len !== msg._contentLength : msg[kBytesWritten] + len > msg._contentLength) | ||
| 900 | + ) { | ||
| 901 | + throw new ERR_HTTP_CONTENT_LENGTH_MISMATCH(len + msg[kBytesWritten], msg._contentLength); | ||
| 902 | + } | ||
| 903 | + | ||
| 904 | + msg[kBytesWritten] += len; | ||
| 905 | + } | ||
| 906 | + | ||
| 917 | 907 | if (!msg._header) { | |
| 918 | 908 | if (fromEnd) { | |
| 909 | + len ??= typeof chunk === 'string' ? Buffer.byteLength(chunk, encoding) : chunk.byteLength; | ||
| 919 | 910 | msg._contentLength = len; | |
| 920 | 911 | } | |
| 921 | 912 | msg._implicitHeader(); | |
@@ -935,12 +926,13 @@ function write_(msg, chunk, encoding, callback, fromEnd) { | |||
| 935 | 926 | ||
| 936 | 927 | let ret; | |
| 937 | 928 | if (msg.chunkedEncoding && chunk.length !== 0) { | |
| 929 | + len ??= typeof chunk === 'string' ? Buffer.byteLength(chunk, encoding) : chunk.byteLength; | ||
| 938 | 930 | msg._send(NumberPrototypeToString(len, 16), 'latin1', null); | |
| 939 | 931 | msg._send(crlf_buf, null, null); | |
| 940 | - msg._send(chunk, encoding, null); | ||
| 932 | + msg._send(chunk, encoding, null, len); | ||
| 941 | 933 | ret = msg._send(crlf_buf, null, callback); | |
| 942 | 934 | } else { | |
| 943 | - ret = msg._send(chunk, encoding, callback); | ||
| 935 | + ret = msg._send(chunk, encoding, callback, len); | ||
| 944 | 936 | } | |
| 945 | 937 | ||
| 946 | 938 | debug('write ret = ' + ret); | |
@@ -1012,8 +1004,6 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { | |||
| 1012 | 1004 | encoding = null; | |
| 1013 | 1005 | } | |
| 1014 | 1006 | ||
| 1015 | - this[kEndCalled] = true; | ||
| 1016 | - | ||
| 1017 | 1007 | if (chunk) { | |
| 1018 | 1008 | if (this.finished) { | |
| 1019 | 1009 | onError(this, | |
@@ -1048,6 +1038,10 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) { | |||
| 1048 | 1038 | if (typeof callback === 'function') | |
| 1049 | 1039 | this.once('finish', callback); | |
| 1050 | 1040 | ||
| 1041 | + if (strictContentLength(this) && this[kBytesWritten] !== this._contentLength) { | ||
| 1042 | + throw new ERR_HTTP_CONTENT_LENGTH_MISMATCH(this[kBytesWritten], this._contentLength); | ||
| 1043 | + } | ||
| 1044 | + | ||
| 1051 | 1045 | const finish = onFinish.bind(undefined, this); | |
| 1052 | 1046 | ||
| 1053 | 1047 | if (this._hasBody && this.chunkedEncoding) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -57,7 +57,7 @@ function shouldThrowOnFewerBytes() { | |||
| 57 | 57 | res.write('a'); | |
| 58 | 58 | res.statusCode = 200; | |
| 59 | 59 | assert.throws(() => { | |
| 60 | - res.end(); | ||
| 60 | + res.end('aaa'); | ||
| 61 | 61 | }, { | |
| 62 | 62 | code: 'ERR_HTTP_CONTENT_LENGTH_MISMATCH' | |
| 63 | 63 | }); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments