@@ -594,59 +594,59 @@ function parserOnIncomingClient(res, shouldKeepAlive) {
594594}
595595
596596// client
597- function responseKeepAlive ( res , req ) {
597+ function responseKeepAlive ( req ) {
598598 const socket = req . socket ;
599599
600- if ( ! req . shouldKeepAlive ) {
601- if ( socket . writable ) {
602- debug ( 'AGENT socket.destroySoon()' ) ;
603- if ( typeof socket . destroySoon === 'function' )
604- socket . destroySoon ( ) ;
605- else
606- socket . end ( ) ;
607- }
608- assert ( ! socket . writable ) ;
609- } else {
610- debug ( 'AGENT socket keep-alive' ) ;
611- if ( req . timeoutCb ) {
612- socket . setTimeout ( 0 , req . timeoutCb ) ;
613- req . timeoutCb = null ;
614- }
615- socket . removeListener ( 'close' , socketCloseListener ) ;
616- socket . removeListener ( 'error' , socketErrorListener ) ;
617- socket . removeListener ( 'drain' , ondrain ) ;
618- socket . once ( 'error' , freeSocketErrorListener ) ;
619- // There are cases where _handle === null. Avoid those. Passing null to
620- // nextTick() will call getDefaultTriggerAsyncId() to retrieve the id.
621- const asyncId = socket . _handle ? socket . _handle . getAsyncId ( ) : undefined ;
622- // Mark this socket as available, AFTER user-added end
623- // handlers have a chance to run.
624- defaultTriggerAsyncIdScope ( asyncId , process . nextTick , emitFreeNT , socket ) ;
625- }
600+ debug ( 'AGENT socket keep-alive' ) ;
601+ if ( req . timeoutCb ) {
602+ socket . setTimeout ( 0 , req . timeoutCb ) ;
603+ req . timeoutCb = null ;
604+ }
605+ socket . removeListener ( 'close' , socketCloseListener ) ;
606+ socket . removeListener ( 'error' , socketErrorListener ) ;
607+ socket . once ( 'error' , freeSocketErrorListener ) ;
608+ // There are cases where _handle === null. Avoid those. Passing null to
609+ // nextTick() will call getDefaultTriggerAsyncId() to retrieve the id.
610+ const asyncId = socket . _handle ? socket . _handle . getAsyncId ( ) : undefined ;
611+ // Mark this socket as available, AFTER user-added end
612+ // handlers have a chance to run.
613+ defaultTriggerAsyncIdScope ( asyncId , process . nextTick , emitFreeNT , socket ) ;
626614}
627615
628616function responseOnEnd ( ) {
629- const res = this ;
630617 const req = this . req ;
631618
632619 if ( req . socket && req . timeoutCb ) {
633620 req . socket . removeListener ( 'timeout' , emitRequestTimeout ) ;
634621 }
635622
636623 req . _ended = true ;
637- if ( ! req . shouldKeepAlive || req . finished )
638- responseKeepAlive ( res , req ) ;
624+
625+ if ( ! req . shouldKeepAlive ) {
626+ const socket = req . socket ;
627+ if ( socket . writable ) {
628+ debug ( 'AGENT socket.destroySoon()' ) ;
629+ if ( typeof socket . destroySoon === 'function' )
630+ socket . destroySoon ( ) ;
631+ else
632+ socket . end ( ) ;
633+ }
634+ assert ( ! socket . writable ) ;
635+ } else if ( req . finished ) {
636+ // We can assume `req.finished` means all data has been written since:
637+ // - `'responseOnEnd'` means we have been assigned a socket.
638+ // - when we have a socket we write directly to it without buffering.
639+ // - `req.finished` means `end()` has been called and no further data.
640+ // can be written
641+ responseKeepAlive ( req ) ;
642+ }
639643}
640644
641645function requestOnPrefinish ( ) {
642646 const req = this ;
643- const res = this . res ;
644-
645- if ( ! req . shouldKeepAlive )
646- return ;
647647
648- if ( req . _ended )
649- responseKeepAlive ( res , req ) ;
648+ if ( req . shouldKeepAlive && req . _ended )
649+ responseKeepAlive ( req ) ;
650650}
651651
652652function emitFreeNT ( socket ) {
0 commit comments