@@ -2541,7 +2541,30 @@ function callStreamClose(stream) {
25412541 stream . close ( ) ;
25422542}
25432543
2544- function processHeaders ( oldHeaders , options ) {
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 ) {
25452568 assertIsObject ( oldHeaders , 'headers' ) ;
25462569 const headers = { __proto__ : null } ;
25472570
@@ -2576,9 +2599,51 @@ function processHeaders(oldHeaders, options) {
25762599 if ( neverIndex !== undefined && ! ArrayIsArray ( neverIndex ) )
25772600 throw new ERR_INVALID_ARG_VALUE ( 'headers[http2.neverIndex]' , neverIndex ) ;
25782601
2579- return headers ;
2602+ return {
2603+ headers,
2604+ statusCode : headers [ HTTP2_HEADER_STATUS ] ,
2605+ } ;
25802606}
25812607
2608+ function prepareResponseHeadersArray ( headers , options ) {
2609+ let statusCode ;
2610+ let isDateSet = false ;
2611+
2612+ for ( let i = 0 ; i < headers . length ; i += 2 ) {
2613+ const header = headers [ i ] . toLowerCase ( ) ;
2614+ const value = headers [ i + 1 ] ;
2615+
2616+ if ( header === HTTP2_HEADER_STATUS ) {
2617+ statusCode = value | 0 ;
2618+ } else if ( header === HTTP2_HEADER_DATE ) {
2619+ isDateSet = true ;
2620+ }
2621+ }
2622+
2623+ if ( ! statusCode ) {
2624+ statusCode = HTTP_STATUS_OK ;
2625+ headers . unshift ( HTTP2_HEADER_STATUS , statusCode ) ;
2626+ }
2627+
2628+ if ( ! isDateSet && ( options . sendDate == null || options . sendDate ) ) {
2629+ headers . push ( HTTP2_HEADER_DATE , utcDate ( ) ) ;
2630+ }
2631+
2632+ // This is intentionally stricter than the HTTP/1 implementation, which
2633+ // allows values between 100 and 999 (inclusive) in order to allow for
2634+ // backwards compatibility with non-spec compliant code. With HTTP/2,
2635+ // we have the opportunity to start fresh with stricter spec compliance.
2636+ // This will have an impact on the compatibility layer for anyone using
2637+ // non-standard, non-compliant status codes.
2638+ if ( statusCode < 200 || statusCode > 599 )
2639+ throw new ERR_HTTP2_STATUS_INVALID ( statusCode ) ;
2640+
2641+ const neverIndex = headers [ kSensitiveHeaders ] ;
2642+ if ( neverIndex !== undefined && ! ArrayIsArray ( neverIndex ) )
2643+ throw new ERR_INVALID_ARG_VALUE ( 'headers[http2.neverIndex]' , neverIndex ) ;
2644+
2645+ return { headers, statusCode } ;
2646+ }
25822647
25832648function onFileUnpipe ( ) {
25842649 const stream = this . sink [ kOwner ] ;
@@ -2882,7 +2947,7 @@ class ServerHttp2Stream extends Http2Stream {
28822947 }
28832948
28842949 // Initiate a response on this Http2Stream
2885- respond ( headers , options ) {
2950+ respond ( headersParam , options ) {
28862951 if ( this . destroyed || this . closed )
28872952 throw new ERR_HTTP2_INVALID_STREAM ( ) ;
28882953 if ( this . headersSent )
@@ -2907,15 +2972,16 @@ class ServerHttp2Stream extends Http2Stream {
29072972 state . flags |= STREAM_FLAGS_HAS_TRAILERS ;
29082973 }
29092974
2910- headers = processHeaders ( headers , options ) ;
2911- const headersList = buildNgHeaderString ( headers , assertValidPseudoHeaderResponse ) ;
2912- this [ kSentHeaders ] = headers ;
2975+ const {
2976+ headers,
2977+ headersList,
2978+ statusCode,
2979+ } = prepareResponseHeaders ( this , headersParam , options ) ;
29132980
29142981 state . flags |= STREAM_FLAGS_HEADERS_SENT ;
29152982
29162983 // Close the writable side if the endStream option is set or status
29172984 // is one of known codes with no payload, or it's a head request
2918- const statusCode = headers [ HTTP2_HEADER_STATUS ] | 0 ;
29192985 if ( ! ! options . endStream ||
29202986 statusCode === HTTP_STATUS_NO_CONTENT ||
29212987 statusCode === HTTP_STATUS_RESET_CONTENT ||
@@ -2945,7 +3011,7 @@ class ServerHttp2Stream extends Http2Stream {
29453011 // regular file, here the fd is passed directly. If the underlying
29463012 // mechanism is not able to read from the fd, then the stream will be
29473013 // reset with an error code.
2948- respondWithFD ( fd , headers , options ) {
3014+ respondWithFD ( fd , headersParam , options ) {
29493015 if ( this . destroyed || this . closed )
29503016 throw new ERR_HTTP2_INVALID_STREAM ( ) ;
29513017 if ( this . headersSent )
@@ -2982,8 +3048,11 @@ class ServerHttp2Stream extends Http2Stream {
29823048 this [ kUpdateTimer ] ( ) ;
29833049 this . ownsFd = false ;
29843050
2985- headers = processHeaders ( headers , options ) ;
2986- const statusCode = headers [ HTTP2_HEADER_STATUS ] |= 0 ;
3051+ const {
3052+ headers,
3053+ statusCode,
3054+ } = prepareResponseHeadersObject ( headersParam , options ) ;
3055+
29873056 // Payload/DATA frames are not permitted in these cases
29883057 if ( statusCode === HTTP_STATUS_NO_CONTENT ||
29893058 statusCode === HTTP_STATUS_RESET_CONTENT ||
@@ -3011,7 +3080,7 @@ class ServerHttp2Stream extends Http2Stream {
30113080 // giving the user an opportunity to verify the details and set additional
30123081 // headers. If statCheck returns false, the operation is aborted and no
30133082 // file details are sent.
3014- respondWithFile ( path , headers , options ) {
3083+ respondWithFile ( path , headersParam , options ) {
30153084 if ( this . destroyed || this . closed )
30163085 throw new ERR_HTTP2_INVALID_STREAM ( ) ;
30173086 if ( this . headersSent )
@@ -3042,8 +3111,11 @@ class ServerHttp2Stream extends Http2Stream {
30423111 this [ kUpdateTimer ] ( ) ;
30433112 this . ownsFd = true ;
30443113
3045- headers = processHeaders ( headers , options ) ;
3046- const statusCode = headers [ HTTP2_HEADER_STATUS ] |= 0 ;
3114+ const {
3115+ headers,
3116+ statusCode,
3117+ } = prepareResponseHeadersObject ( headersParam , options ) ;
3118+
30473119 // Payload/DATA frames are not permitted in these cases
30483120 if ( statusCode === HTTP_STATUS_NO_CONTENT ||
30493121 statusCode === HTTP_STATUS_RESET_CONTENT ||
0 commit comments