@@ -2560,8 +2560,31 @@ function callStreamClose(stream) {
25602560 stream . close ( ) ;
25612561}
25622562
2563- function processHeaders ( oldHeaders , options ) {
2564- assertIsObject ( oldHeaders , 'headers' ) ;
2563+ function prepareResponseHeaders ( stream , headersParam , options ) {
2564+ let headers ;
2565+ let statusCode ;
2566+
2567+ if ( ArrayIsArray ( headersParam ) ) {
2568+ ( {
2569+ headers,
2570+ statusCode,
2571+ } = prepareResponseHeadersArray ( headersParam , options ) ) ;
2572+ stream [ kRawHeaders ] = headers ;
2573+ } else {
2574+ ( {
2575+ headers,
2576+ statusCode,
2577+ } = prepareResponseHeadersObject ( headersParam , options ) ) ;
2578+ stream [ kSentHeaders ] = headers ;
2579+ }
2580+
2581+ const headersList = buildNgHeaderString ( headers , assertValidPseudoHeaderResponse ) ;
2582+
2583+ return { headers, headersList, statusCode } ;
2584+ }
2585+
2586+ function prepareResponseHeadersObject ( oldHeaders , options ) {
2587+ assertIsObject ( oldHeaders , 'headers' , [ 'Object' , 'Array' ] ) ;
25652588 const headers = { __proto__ : null } ;
25662589
25672590 if ( oldHeaders !== null && oldHeaders !== undefined ) {
@@ -2582,23 +2605,58 @@ function processHeaders(oldHeaders, options) {
25822605 headers [ HTTP2_HEADER_DATE ] ??= utcDate ( ) ;
25832606 }
25842607
2608+ validatePreparedResponseHeaders ( headers , statusCode ) ;
2609+
2610+ return {
2611+ headers,
2612+ statusCode : headers [ HTTP2_HEADER_STATUS ] ,
2613+ } ;
2614+ }
2615+
2616+ function prepareResponseHeadersArray ( headers , options ) {
2617+ let statusCode ;
2618+ let isDateSet = false ;
2619+
2620+ for ( let i = 0 ; i < headers . length ; i += 2 ) {
2621+ const header = headers [ i ] . toLowerCase ( ) ;
2622+ const value = headers [ i + 1 ] ;
2623+
2624+ if ( header === HTTP2_HEADER_STATUS ) {
2625+ statusCode = value | 0 ;
2626+ } else if ( header === HTTP2_HEADER_DATE ) {
2627+ isDateSet = true ;
2628+ }
2629+ }
2630+
2631+ if ( ! statusCode ) {
2632+ statusCode = HTTP_STATUS_OK ;
2633+ headers . unshift ( HTTP2_HEADER_STATUS , statusCode ) ;
2634+ }
2635+
2636+ if ( ! isDateSet && ( options . sendDate == null || options . sendDate ) ) {
2637+ headers . push ( HTTP2_HEADER_DATE , utcDate ( ) ) ;
2638+ }
2639+
2640+ validatePreparedResponseHeaders ( headers , statusCode ) ;
2641+
2642+ return { headers, statusCode } ;
2643+ }
2644+
2645+ function validatePreparedResponseHeaders ( headers , statusCode ) {
25852646 // This is intentionally stricter than the HTTP/1 implementation, which
25862647 // allows values between 100 and 999 (inclusive) in order to allow for
25872648 // backwards compatibility with non-spec compliant code. With HTTP/2,
25882649 // we have the opportunity to start fresh with stricter spec compliance.
25892650 // This will have an impact on the compatibility layer for anyone using
25902651 // non-standard, non-compliant status codes.
25912652 if ( statusCode < 200 || statusCode > 599 )
2592- throw new ERR_HTTP2_STATUS_INVALID ( headers [ HTTP2_HEADER_STATUS ] ) ;
2653+ throw new ERR_HTTP2_STATUS_INVALID ( statusCode ) ;
25932654
25942655 const neverIndex = headers [ kSensitiveHeaders ] ;
25952656 if ( neverIndex !== undefined && ! ArrayIsArray ( neverIndex ) )
25962657 throw new ERR_INVALID_ARG_VALUE ( 'headers[http2.neverIndex]' , neverIndex ) ;
2597-
2598- return headers ;
25992658}
26002659
2601-
26022660function onFileUnpipe ( ) {
26032661 const stream = this . sink [ kOwner ] ;
26042662 if ( stream . ownsFd )
@@ -2901,7 +2959,7 @@ class ServerHttp2Stream extends Http2Stream {
29012959 }
29022960
29032961 // Initiate a response on this Http2Stream
2904- respond ( headers , options ) {
2962+ respond ( headersParam , options ) {
29052963 if ( this . destroyed || this . closed )
29062964 throw new ERR_HTTP2_INVALID_STREAM ( ) ;
29072965 if ( this . headersSent )
@@ -2926,15 +2984,16 @@ class ServerHttp2Stream extends Http2Stream {
29262984 state . flags |= STREAM_FLAGS_HAS_TRAILERS ;
29272985 }
29282986
2929- headers = processHeaders ( headers , options ) ;
2930- const headersList = buildNgHeaderString ( headers , assertValidPseudoHeaderResponse ) ;
2931- this [ kSentHeaders ] = headers ;
2987+ const {
2988+ headers,
2989+ headersList,
2990+ statusCode,
2991+ } = prepareResponseHeaders ( this , headersParam , options ) ;
29322992
29332993 state . flags |= STREAM_FLAGS_HEADERS_SENT ;
29342994
29352995 // Close the writable side if the endStream option is set or status
29362996 // is one of known codes with no payload, or it's a head request
2937- const statusCode = headers [ HTTP2_HEADER_STATUS ] | 0 ;
29382997 if ( ! ! options . endStream ||
29392998 statusCode === HTTP_STATUS_NO_CONTENT ||
29402999 statusCode === HTTP_STATUS_RESET_CONTENT ||
@@ -2964,7 +3023,7 @@ class ServerHttp2Stream extends Http2Stream {
29643023 // regular file, here the fd is passed directly. If the underlying
29653024 // mechanism is not able to read from the fd, then the stream will be
29663025 // reset with an error code.
2967- respondWithFD ( fd , headers , options ) {
3026+ respondWithFD ( fd , headersParam , options ) {
29683027 if ( this . destroyed || this . closed )
29693028 throw new ERR_HTTP2_INVALID_STREAM ( ) ;
29703029 if ( this . headersSent )
@@ -3001,8 +3060,11 @@ class ServerHttp2Stream extends Http2Stream {
30013060 this [ kUpdateTimer ] ( ) ;
30023061 this . ownsFd = false ;
30033062
3004- headers = processHeaders ( headers , options ) ;
3005- const statusCode = headers [ HTTP2_HEADER_STATUS ] |= 0 ;
3063+ const {
3064+ headers,
3065+ statusCode,
3066+ } = prepareResponseHeadersObject ( headersParam , options ) ;
3067+
30063068 // Payload/DATA frames are not permitted in these cases
30073069 if ( statusCode === HTTP_STATUS_NO_CONTENT ||
30083070 statusCode === HTTP_STATUS_RESET_CONTENT ||
@@ -3030,7 +3092,7 @@ class ServerHttp2Stream extends Http2Stream {
30303092 // giving the user an opportunity to verify the details and set additional
30313093 // headers. If statCheck returns false, the operation is aborted and no
30323094 // file details are sent.
3033- respondWithFile ( path , headers , options ) {
3095+ respondWithFile ( path , headersParam , options ) {
30343096 if ( this . destroyed || this . closed )
30353097 throw new ERR_HTTP2_INVALID_STREAM ( ) ;
30363098 if ( this . headersSent )
@@ -3061,8 +3123,11 @@ class ServerHttp2Stream extends Http2Stream {
30613123 this [ kUpdateTimer ] ( ) ;
30623124 this . ownsFd = true ;
30633125
3064- headers = processHeaders ( headers , options ) ;
3065- const statusCode = headers [ HTTP2_HEADER_STATUS ] |= 0 ;
3126+ const {
3127+ headers,
3128+ statusCode,
3129+ } = prepareResponseHeadersObject ( headersParam , options ) ;
3130+
30663131 // Payload/DATA frames are not permitted in these cases
30673132 if ( statusCode === HTTP_STATUS_NO_CONTENT ||
30683133 statusCode === HTTP_STATUS_RESET_CONTENT ||
0 commit comments