import HeaderGenerator from 'header-generator' ; import { OutgoingMessage , Agent , ClientRequest , ClientRequestArgs } from 'http' ; import { WrappedAgent } from './wrapped-agent' ; const { _storeHeader } = OutgoingMessage . prototype ; const generator = new HeaderGenerator ( ) ; /**
 * Transforms the casing of the headers to Pascal-Case.
 */ export class TransformHeadersAgent < T extends Agent > extends WrappedAgent < T > { /**
     * Transforms the request via header normalization.
     */ transformRequest ( request , { sortHeaders } ) { const headers = { } ; const hasConnection = request . hasHeader ( 'connection' ) ; const hasContentLength = request . hasHeader ( 'content-length' ) ; const hasTransferEncoding = request . hasHeader ( 'transfer-encoding' ) ; const hasTrailer = request . hasHeader ( 'trailer' ) ; const keys = request . getHeaderNames ( ) ; for ( const key of keys ) { if ( key . toLowerCase ( ) . startsWith ( 'x-' ) ) { headers [ key ] = request . getHeader ( key ) ! ; } else { headers [ this . toPascalCase ( key ) ] = request . getHeader ( key ) ! ; } if ( sortHeaders ) { request . removeHeader ( key ) ; } } const typedRequest = request as ClientRequest & { _removedContLen : boolean ; _contentLength : number ; _removedTE : boolean ; agent ? : Agent ; } ; if ( ! hasConnection ) { const shouldSendKeepAlive = request . shouldKeepAlive && ( hasContentLength || request . useChunkedEncodingByDefault || typedRequest . agent ) ; if ( shouldSendKeepAlive ) { headers . Connection = 'keep-alive' ; } else { headers . Connection = 'close' ; } } if ( ! hasContentLength && ! hasTransferEncoding ) { if ( ! hasTrailer && ! typedRequest . _removedContLen && typeof typedRequest . _contentLength === 'number' ) { headers [ 'Content-Length' ] = typedRequest . _contentLength ; } else if ( ! typedRequest . _removedTE ) { headers [ 'Transfer-Encoding' ] = 'chunked' ; } } const transformedHeaders = sortHeaders ? generator . orderHeaders ( headers ) : headers ; for ( const [ key , value ] of Object . entries ( transformedHeaders ) ) { request . setHeader ( key , value ) ; } } override addRequest ( request , options ) { const typedRequest = request as ClientRequest & { _storeHeader : ( firstLine : string , headers : Record < string , string > ) => void ; } ; typedRequest . _storeHeader = ( ... args ) => { this . transformRequest ( request , { sortHeaders : true } ) ; return _storeHeader . call ( request , ... args ) ; } ; ( options as any ) . secureEndpoint = options . protocol === 'https:' ; return super . addRequest ( request , options ) ; } toPascalCase ( header ) { return header . split ( '-' ) . map ( ( part ) => { return part [ 0 ] ! . toUpperCase ( ) + part . slice ( 1 ) . toLowerCase ( ) ; } ) . join ( '-' ) ; } }