@@ -2541,8 +2541,31 @@ function callStreamClose(stream) {
25412541 stream . close ( ) ;
25422542}
25432543
2544- function processHeaders ( oldHeaders , options ) {
2545- assertIsObject ( oldHeaders , 'headers' ) ;
2544+ function prepareResponseHeaders ( stream , headersParam , options ) {
2545+ let headers ;
2546+ let statusCode ;
2547+
2548+ if ( ArrayIsArray ( headersParam ) ) {
2549+ ( {
2550+ headers,
2551+ statusCode,
2552+ } = prepareResponseHeadersArray ( headersParam , options ) ) ;
2553+ stream [ kRawHeaders ] = headers ;
2554+ } else {
2555+ ( {
2556+ headers,
2557+ statusCode,
2558+ } = prepareResponseHeadersObject ( headersParam , options ) ) ;
2559+ stream [ kSentHeaders ] = headers ;
2560+ }
2561+
2562+ const headersList = buildNgHeaderString ( headers , assertValidPseudoHeaderResponse ) ;
2563+
2564+ return { headers, headersList, statusCode } ;
2565+ }
2566+
2567+ function prepareResponseHeadersObject ( oldHeaders , options ) {
2568+ assertIsObject ( oldHeaders , 'headers' , [ 'Object' , 'Array' ] ) ;
25462569 const headers = { __proto__ : null } ;
25472570
25482571 if ( oldHeaders !== null && oldHeaders !== undefined ) {
@@ -2563,23 +2586,58 @@ function processHeaders(oldHeaders, options) {
25632586 headers [ HTTP2_HEADER_DATE ] ??= utcDate ( ) ;
25642587 }
25652588
2589+ validatePreparedResponseHeaders ( headers , statusCode ) ;
2590+
2591+ return {
2592+ headers,
2593+ statusCode : headers [ HTTP2_HEADER_STATUS ] ,
2594+ } ;
2595+ }
2596+
2597+ function prepareResponseHeadersArray ( headers , options ) {
2598+ let statusCode ;
2599+ let isDateSet = false ;
2600+
2601+ for ( let i = 0 ; i < headers . length ; i += 2 ) {
2602+ const header = headers [ i ] . toLowerCase ( ) ;
2603+ const value = headers [ i + 1 ] ;
2604+
2605+ if ( header === HTTP2_HEADER_STATUS ) {
2606+ statusCode = value | 0 ;
2607+ } else if ( header === HTTP2_HEADER_DATE ) {
2608+ isDateSet = true ;
2609+ }
2610+ }
2611+
2612+ if ( ! statusCode ) {
2613+ statusCode = HTTP_STATUS_OK ;
2614+ headers . unshift ( HTTP2_HEADER_STATUS , statusCode ) ;
2615+ }
2616+
2617+ if ( ! isDateSet && ( options . sendDate == null || options . sendDate ) ) {
2618+ headers . push ( HTTP2_HEADER_DATE , utcDate ( ) ) ;
2619+ }
2620+
2621+ validatePreparedResponseHeaders ( headers , statusCode ) ;
2622+
2623+ return { headers, statusCode } ;
2624+ }
2625+
2626+ function validatePreparedResponseHeaders ( headers , statusCode ) {
25662627 // This is intentionally stricter than the HTTP/1 implementation, which
25672628 // allows values between 100 and 999 (inclusive) in order to allow for
25682629 // backwards compatibility with non-spec compliant code. With HTTP/2,
25692630 // we have the opportunity to start fresh with stricter spec compliance.
25702631 // This will have an impact on the compatibility layer for anyone using
25712632 // non-standard, non-compliant status codes.
25722633 if ( statusCode < 200 || statusCode > 599 )
2573- throw new ERR_HTTP2_STATUS_INVALID ( headers [ HTTP2_HEADER_STATUS ] ) ;
2634+ throw new ERR_HTTP2_STATUS_INVALID ( statusCode ) ;
25742635
25752636 const neverIndex = headers [ kSensitiveHeaders ] ;
25762637 if ( neverIndex !== undefined && ! ArrayIsArray ( neverIndex ) )
25772638 throw new ERR_INVALID_ARG_VALUE ( 'headers[http2.neverIndex]' , neverIndex ) ;
2578-
2579- return headers ;
25802639}
25812640
2582-
25832641function onFileUnpipe ( ) {
25842642 const stream = this . sink [ kOwner ] ;
25852643 if ( stream . ownsFd )
@@ -2882,7 +2940,7 @@ class ServerHttp2Stream extends Http2Stream {
28822940 }
28832941
28842942 // Initiate a response on this Http2Stream
2885- respond ( headers , options ) {
2943+ respond ( headersParam , options ) {
28862944 if ( this . destroyed || this . closed )
28872945 throw new ERR_HTTP2_INVALID_STREAM ( ) ;
28882946 if ( this . headersSent )
@@ -2907,15 +2965,16 @@ class ServerHttp2Stream extends Http2Stream {
29072965 state . flags |= STREAM_FLAGS_HAS_TRAILERS ;
29082966 }
29092967
2910- headers = processHeaders ( headers , options ) ;
2911- const headersList = buildNgHeaderString ( headers , assertValidPseudoHeaderResponse ) ;
2912- this [ kSentHeaders ] = headers ;
2968+ const {
2969+ headers,
2970+ headersList,
2971+ statusCode,
2972+ } = prepareResponseHeaders ( this , headersParam , options ) ;
29132973
29142974 state . flags |= STREAM_FLAGS_HEADERS_SENT ;
29152975
29162976 // Close the writable side if the endStream option is set or status
29172977 // is one of known codes with no payload, or it's a head request
2918- const statusCode = headers [ HTTP2_HEADER_STATUS ] | 0 ;
29192978 if ( ! ! options . endStream ||
29202979 statusCode === HTTP_STATUS_NO_CONTENT ||
29212980 statusCode === HTTP_STATUS_RESET_CONTENT ||
@@ -2945,7 +3004,7 @@ class ServerHttp2Stream extends Http2Stream {
29453004 // regular file, here the fd is passed directly. If the underlying
29463005 // mechanism is not able to read from the fd, then the stream will be
29473006 // reset with an error code.
2948- respondWithFD ( fd , headers , options ) {
3007+ respondWithFD ( fd , headersParam , options ) {
29493008 if ( this . destroyed || this . closed )
29503009 throw new ERR_HTTP2_INVALID_STREAM ( ) ;
29513010 if ( this . headersSent )
@@ -2982,8 +3041,11 @@ class ServerHttp2Stream extends Http2Stream {
29823041 this [ kUpdateTimer ] ( ) ;
29833042 this . ownsFd = false ;
29843043
2985- headers = processHeaders ( headers , options ) ;
2986- const statusCode = headers [ HTTP2_HEADER_STATUS ] |= 0 ;
3044+ const {
3045+ headers,
3046+ statusCode,
3047+ } = prepareResponseHeadersObject ( headersParam , options ) ;
3048+
29873049 // Payload/DATA frames are not permitted in these cases
29883050 if ( statusCode === HTTP_STATUS_NO_CONTENT ||
29893051 statusCode === HTTP_STATUS_RESET_CONTENT ||
@@ -3011,7 +3073,7 @@ class ServerHttp2Stream extends Http2Stream {
30113073 // giving the user an opportunity to verify the details and set additional
30123074 // headers. If statCheck returns false, the operation is aborted and no
30133075 // file details are sent.
3014- respondWithFile ( path , headers , options ) {
3076+ respondWithFile ( path , headersParam , options ) {
30153077 if ( this . destroyed || this . closed )
30163078 throw new ERR_HTTP2_INVALID_STREAM ( ) ;
30173079 if ( this . headersSent )
@@ -3042,8 +3104,11 @@ class ServerHttp2Stream extends Http2Stream {
30423104 this [ kUpdateTimer ] ( ) ;
30433105 this . ownsFd = true ;
30443106
3045- headers = processHeaders ( headers , options ) ;
3046- const statusCode = headers [ HTTP2_HEADER_STATUS ] |= 0 ;
3107+ const {
3108+ headers,
3109+ statusCode,
3110+ } = prepareResponseHeadersObject ( headersParam , options ) ;
3111+
30473112 // Payload/DATA frames are not permitted in these cases
30483113 if ( statusCode === HTTP_STATUS_NO_CONTENT ||
30493114 statusCode === HTTP_STATUS_RESET_CONTENT ||
0 commit comments