@@ -1506,6 +1506,13 @@ class Http2Stream extends Duplex {
15061506 this . once ( 'ready' , this . _destroy . bind ( this , err , callback ) ) ;
15071507 return ;
15081508 }
1509+
1510+ const server = session [ kServer ] ;
1511+
1512+ if ( err && server ) {
1513+ server . emit ( 'streamError' , err , this ) ;
1514+ }
1515+
15091516 process . nextTick ( ( ) => {
15101517 debug ( `[${ sessionName ( session [ kType ] ) } ] destroying stream ${ this [ kID ] } ` ) ;
15111518
@@ -1529,9 +1536,8 @@ class Http2Stream extends Duplex {
15291536 // All done
15301537 const rst = this [ kState ] . rst ;
15311538 const code = rst ? this [ kState ] . rstCode : NGHTTP2_NO_ERROR ;
1532- if ( code !== NGHTTP2_NO_ERROR ) {
1533- const err = new errors . Error ( 'ERR_HTTP2_STREAM_ERROR' , code ) ;
1534- process . nextTick ( ( ) => this . emit ( 'error' , err ) ) ;
1539+ if ( ! err && code !== NGHTTP2_NO_ERROR ) {
1540+ err = new errors . Error ( 'ERR_HTTP2_STREAM_ERROR' , code ) ;
15351541 }
15361542 process . nextTick ( emit . bind ( this , 'streamClosed' , code ) ) ;
15371543 debug ( `[${ sessionName ( session [ kType ] ) } ] stream ${ this [ kID ] } destroyed` ) ;
@@ -1634,13 +1640,24 @@ function doSendFileFD(session, options, fd, headers, getTrailers, err, stat) {
16341640 abort ( this ) ;
16351641 return ;
16361642 }
1643+ const onError = options . onError ;
1644+
16371645 if ( err ) {
1638- process . nextTick ( ( ) => this . emit ( 'error' , err ) ) ;
1646+ if ( onError ) {
1647+ onError ( err ) ;
1648+ } else {
1649+ this . destroy ( err ) ;
1650+ }
16391651 return ;
16401652 }
1653+
16411654 if ( ! stat . isFile ( ) ) {
16421655 err = new errors . Error ( 'ERR_HTTP2_SEND_FILE' ) ;
1643- process . nextTick ( ( ) => this . emit ( 'error' , err ) ) ;
1656+ if ( onError ) {
1657+ onError ( err ) ;
1658+ } else {
1659+ this . destroy ( err ) ;
1660+ }
16441661 return ;
16451662 }
16461663
@@ -1677,12 +1694,17 @@ function doSendFileFD(session, options, fd, headers, getTrailers, err, stat) {
16771694
16781695function afterOpen ( session , options , headers , getTrailers , err , fd ) {
16791696 const state = this [ kState ] ;
1697+ const onError = options . onError ;
16801698 if ( this . destroyed || session . destroyed ) {
16811699 abort ( this ) ;
16821700 return ;
16831701 }
16841702 if ( err ) {
1685- process . nextTick ( ( ) => this . emit ( 'error' , err ) ) ;
1703+ if ( onError ) {
1704+ onError ( err ) ;
1705+ } else {
1706+ this . destroy ( err ) ;
1707+ }
16861708 return ;
16871709 }
16881710 state . fd = fd ;
@@ -1691,13 +1713,20 @@ function afterOpen(session, options, headers, getTrailers, err, fd) {
16911713 doSendFileFD . bind ( this , session , options , fd , headers , getTrailers ) ) ;
16921714}
16931715
1716+ function streamOnError ( err ) {
1717+ // we swallow the error for parity with HTTP1
1718+ // all the errors that ends here are not critical for the project
1719+ debug ( 'ServerHttp2Stream errored, avoiding uncaughtException' , err ) ;
1720+ }
1721+
16941722
16951723class ServerHttp2Stream extends Http2Stream {
16961724 constructor ( session , id , options , headers ) {
16971725 super ( session , options ) ;
16981726 this [ kInit ] ( id ) ;
16991727 this [ kProtocol ] = headers [ HTTP2_HEADER_SCHEME ] ;
17001728 this [ kAuthority ] = headers [ HTTP2_HEADER_AUTHORITY ] ;
1729+ this . on ( 'error' , streamOnError ) ;
17011730 debug ( `[${ sessionName ( session [ kType ] ) } ] created serverhttp2stream` ) ;
17021731 }
17031732
@@ -2556,6 +2585,8 @@ module.exports = {
25562585 createServer,
25572586 createSecureServer,
25582587 connect,
2588+ Http2Session,
2589+ Http2Stream,
25592590 Http2ServerRequest,
25602591 Http2ServerResponse
25612592} ;
0 commit comments