@@ -25,7 +25,6 @@ const {
2525  Array, 
2626  ArrayIsArray, 
2727  ArrayPrototypeJoin, 
28-   MathAbs, 
2928  MathFloor, 
3029  NumberPrototypeToString, 
3130  ObjectCreate, 
@@ -87,7 +86,6 @@ const HIGH_WATER_MARK = getDefaultHighWaterMark();
8786const  kCorked  =  Symbol ( 'corked' ) ; 
8887const  kUniqueHeaders  =  Symbol ( 'kUniqueHeaders' ) ; 
8988const  kBytesWritten  =  Symbol ( 'kBytesWritten' ) ; 
90- const  kEndCalled  =  Symbol ( 'kEndCalled' ) ; 
9189const  kErrored  =  Symbol ( 'errored' ) ; 
9290
9391const  nop  =  ( )  =>  { } ; 
@@ -134,7 +132,6 @@ function OutgoingMessage() {
134132
135133  this . strictContentLength  =  false ; 
136134  this [ kBytesWritten ]  =  0 ; 
137-   this [ kEndCalled ]  =  false ; 
138135  this . _contentLength  =  null ; 
139136  this . _hasBody  =  true ; 
140137  this . _trailer  =  '' ; 
@@ -356,7 +353,7 @@ OutgoingMessage.prototype.destroy = function destroy(error) {
356353
357354
358355// 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 )  { 
360357  // This is a shameful hack to get the headers and first body chunk onto 
361358  // the same packet. Future versions of Node are going to take care of 
362359  // this at a lower level and in a more general way. 
@@ -378,20 +375,11 @@ OutgoingMessage.prototype._send = function _send(data, encoding, callback) {
378375    } 
379376    this . _headerSent  =  true ; 
380377  } 
381-   return  this . _writeRaw ( data ,  encoding ,  callback ) ; 
378+   return  this . _writeRaw ( data ,  encoding ,  callback ,   byteLength ) ; 
382379} ; 
383380
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- 
393381OutgoingMessage . prototype . _writeRaw  =  _writeRaw ; 
394- function  _writeRaw ( data ,  encoding ,  callback )  { 
382+ function  _writeRaw ( data ,  encoding ,  callback ,   size )  { 
395383  const  conn  =  this . socket ; 
396384  if  ( conn  &&  conn . destroyed )  { 
397385    // The socket was destroyed. If we're still trying to write to it, 
@@ -404,25 +392,6 @@ function _writeRaw(data, encoding, callback) {
404392    encoding  =  null ; 
405393  } 
406394
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- 
426395  if  ( conn  &&  conn . _httpMessage  ===  this  &&  conn . writable )  { 
427396    // There might be pending data in the this.output buffer. 
428397    if  ( this . outputData . length )  { 
@@ -882,18 +851,24 @@ function emitErrorNt(msg, err, callback) {
882851  } 
883852} 
884853
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+ 
885865function  write_ ( msg ,  chunk ,  encoding ,  callback ,  fromEnd )  { 
886866  if  ( typeof  callback  !==  'function' ) 
887867    callback  =  nop ; 
888868
889-   let  len ; 
890869  if  ( chunk  ===  null )  { 
891870    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 ) )  { 
897872    throw  new  ERR_INVALID_ARG_TYPE ( 
898873      'chunk' ,  [ 'string' ,  'Buffer' ,  'Uint8Array' ] ,  chunk ) ; 
899874  } 
@@ -914,8 +889,24 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
914889    return  false ; 
915890  } 
916891
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+ 
917907  if  ( ! msg . _header )  { 
918908    if  ( fromEnd )  { 
909+       len  ??=  typeof  chunk  ===  'string'  ? Buffer . byteLength ( chunk ,  encoding )  : chunk . byteLength ; 
919910      msg . _contentLength  =  len ; 
920911    } 
921912    msg . _implicitHeader ( ) ; 
@@ -935,12 +926,13 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
935926
936927  let  ret ; 
937928  if  ( msg . chunkedEncoding  &&  chunk . length  !==  0 )  { 
929+     len  ??=  typeof  chunk  ===  'string'  ? Buffer . byteLength ( chunk ,  encoding )  : chunk . byteLength ; 
938930    msg . _send ( NumberPrototypeToString ( len ,  16 ) ,  'latin1' ,  null ) ; 
939931    msg . _send ( crlf_buf ,  null ,  null ) ; 
940-     msg . _send ( chunk ,  encoding ,  null ) ; 
932+     msg . _send ( chunk ,  encoding ,  null ,   len ) ; 
941933    ret  =  msg . _send ( crlf_buf ,  null ,  callback ) ; 
942934  }  else  { 
943-     ret  =  msg . _send ( chunk ,  encoding ,  callback ) ; 
935+     ret  =  msg . _send ( chunk ,  encoding ,  callback ,   len ) ; 
944936  } 
945937
946938  debug ( 'write ret = '  +  ret ) ; 
@@ -1012,8 +1004,6 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
10121004    encoding  =  null ; 
10131005  } 
10141006
1015-   this [ kEndCalled ]  =  true ; 
1016- 
10171007  if  ( chunk )  { 
10181008    if  ( this . finished )  { 
10191009      onError ( this , 
@@ -1048,6 +1038,10 @@ OutgoingMessage.prototype.end = function end(chunk, encoding, callback) {
10481038  if  ( typeof  callback  ===  'function' ) 
10491039    this . once ( 'finish' ,  callback ) ; 
10501040
1041+   if  ( strictContentLength ( this )  &&  this [ kBytesWritten ]  !==  this . _contentLength )  { 
1042+     throw  new  ERR_HTTP_CONTENT_LENGTH_MISMATCH ( this [ kBytesWritten ] ,  this . _contentLength ) ; 
1043+   } 
1044+ 
10511045  const  finish  =  onFinish . bind ( undefined ,  this ) ; 
10521046
10531047  if  ( this . _hasBody  &&  this . chunkedEncoding )  { 
0 commit comments