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