@@ -2541,8 +2541,31 @@ function callStreamClose(stream) {
25412541stream . 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' ] ) ;
25462569const headers = { __proto__ : null } ;
25472570
25482571if ( oldHeaders !== null && oldHeaders !== undefined ) {
@@ -2563,23 +2586,58 @@ function processHeaders(oldHeaders, options) {
25632586headers [ 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.
25722633if ( statusCode < 200 || statusCode > 599 )
2573- throw new ERR_HTTP2_STATUS_INVALID ( headers [ HTTP2_HEADER_STATUS ] ) ;
2634+ throw new ERR_HTTP2_STATUS_INVALID ( statusCode ) ;
25742635
25752636const neverIndex = headers [ kSensitiveHeaders ] ;
25762637if ( neverIndex !== undefined && ! ArrayIsArray ( neverIndex ) )
25772638throw new ERR_INVALID_ARG_VALUE ( 'headers[http2.neverIndex]' , neverIndex ) ;
2578-
2579- return headers ;
25802639}
25812640
2582-
25832641function onFileUnpipe ( ) {
25842642const stream = this . sink [ kOwner ] ;
25852643if ( 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 ) {
28862944if ( this . destroyed || this . closed )
28872945throw new ERR_HTTP2_INVALID_STREAM ( ) ;
28882946if ( this . headersSent )
@@ -2907,15 +2965,16 @@ class ServerHttp2Stream extends Http2Stream {
29072965state . 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
29142974state . 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 ;
29192978if ( ! ! options . endStream ||
29202979statusCode === HTTP_STATUS_NO_CONTENT ||
29212980statusCode === 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 ) {
29493008if ( this . destroyed || this . closed )
29503009throw new ERR_HTTP2_INVALID_STREAM ( ) ;
29513010if ( this . headersSent )
@@ -2982,8 +3041,11 @@ class ServerHttp2Stream extends Http2Stream {
29823041this [ kUpdateTimer ] ( ) ;
29833042this . 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
29883050if ( statusCode === HTTP_STATUS_NO_CONTENT ||
29893051statusCode === 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 ) {
30153077if ( this . destroyed || this . closed )
30163078throw new ERR_HTTP2_INVALID_STREAM ( ) ;
30173079if ( this . headersSent )
@@ -3042,8 +3104,11 @@ class ServerHttp2Stream extends Http2Stream {
30423104this [ kUpdateTimer ] ( ) ;
30433105this . 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
30483113if ( statusCode === HTTP_STATUS_NO_CONTENT ||
30493114statusCode === HTTP_STATUS_RESET_CONTENT ||
0 commit comments