11import { Writable } from 'stream' ;
2+ import { IncomingHttpHeaders } from 'http' ;
23import ServerlessRequest from './serverlessRequest' ;
34import ServerlessResponse from './serverlessResponse' ;
45
6+ type MultiValueHeaders = {
7+ [ key : string ] : string [ ] ;
8+ } ;
59export const waitForStreamComplete = ( stream : Writable ) : Promise < Writable > => {
610 if ( stream . writableFinished || stream . writableEnded ) {
711 return Promise . resolve ( stream ) ;
812 }
913
1014 return new Promise ( ( resolve , reject ) => {
11- stream . once ( 'error' , complete ) ;
12- stream . once ( 'end' , complete ) ;
13- stream . once ( 'finish' , complete ) ;
14-
1515 let isComplete = false ;
1616
1717 function complete ( err ?: Error ) {
@@ -31,20 +31,65 @@ export const waitForStreamComplete = (stream: Writable): Promise<Writable> => {
3131 resolve ( stream ) ;
3232 }
3333 }
34+
35+ stream . once ( 'error' , complete ) ;
36+ stream . once ( 'end' , complete ) ;
37+ stream . once ( 'finish' , complete ) ;
3438 } ) ;
3539} ;
3640
41+ const sanitizeHeaders = ( headers : IncomingHttpHeaders ) => {
42+ return Object . keys ( headers ) . reduce (
43+ ( memo , key ) => {
44+ const value = headers [ key ] ;
45+
46+ if ( Array . isArray ( value ) ) {
47+ memo . multiValueHeaders [ key ] = value ;
48+ if ( key . toLowerCase ( ) !== 'set-cookie' ) {
49+ memo . headers [ key ] = value . join ( ', ' ) ;
50+ }
51+ } else {
52+ memo . headers [ key ] = value == null ? '' : value . toString ( ) ;
53+ }
54+
55+ return memo ;
56+ } ,
57+ {
58+ headers : { } as IncomingHttpHeaders ,
59+ multiValueHeaders : { } as MultiValueHeaders ,
60+ } ,
61+ ) ;
62+ } ;
63+
3764export const buildResponse = ( {
3865 request,
3966 response,
4067} : {
4168 request : ServerlessRequest ;
4269 response : ServerlessResponse ;
4370} ) => {
71+ const { headers, multiValueHeaders } = sanitizeHeaders ( ServerlessResponse . headers ( response ) ) ;
72+
73+ let body = ServerlessResponse . body ( response ) . toString (
74+ request . isBase64Encoded ? 'base64' : 'utf8' ,
75+ ) ;
76+ if ( headers [ 'transfer-encoding' ] === 'chunked' || response . chunkedEncoding ) {
77+ const raw = ServerlessResponse . body ( response ) . toString ( ) . split ( '\r\n' ) ;
78+ const parsed = [ ] ;
79+ for ( let i = 0 ; i < raw . length ; i += 2 ) {
80+ const size = parseInt ( raw [ i ] , 16 ) ;
81+ const value = raw [ i + 1 ] ;
82+ if ( value ) {
83+ parsed . push ( value . substring ( 0 , size ) ) ;
84+ }
85+ }
86+ body = parsed . join ( '' ) ;
87+ }
4488 return {
4589 statusCode : response . statusCode ,
46- body : ServerlessResponse . body ( response ) . toString ( request . isBase64Encoded ? 'base64' : 'utf8' ) ,
47- headers : response . headers ,
90+ body,
91+ headers,
92+ multiValueHeaders,
4893 isBase64Encoded : request . isBase64Encoded ,
4994 } ;
5095} ;
0 commit comments