import { RequestDescriptor } from './request' ; import { ProtoCtx } from '../protobuf/protobuf' ; import { convertHeaders , unconvertHeaders } from './headers' ; import { ResponseBodyValue , ResponseDescriptor , ResponseBodyType } from './response' ; import fetch , { Response } from 'node-fetch' ; import { deserializeProtobuf } from '../protobuf/deserializer' ; import https from 'https' ; const CONTENT_TYPE_JSON = 'application/json' ; const CONTENT_TYPE_HTML = 'text/html' ; export async function makeRequest ( request , protoCtx ) { const { url , method , body } = request ; const headers = convertHeaders ( request . headers ) ; const sTime = Date . now ( ) ; const agent = new https . Agent ( { rejectUnauthorized : false , } ) ; const resp = await fetch ( url , { method , body , headers , agent } ) ; const eTime = Date . now ( ) ; const dt = eTime - sTime ; return translateResponse ( resp , request , protoCtx , dt ) ; } async function translateResponse ( response , request , protoCtx , dt ) { const responseHeaders = unconvertHeaders ( response . headers ) ; const saidContentType = responseHeaders . find ( ( [ name ] ) => name === 'content-type' ) ?. [ 1 ] ; const { expectedProtobufMsg , expectedProtobufMsgOnError } = request ; let responseBodyType = 'unknown' ; let responseBodyValue = undefined ; let warning = undefined ; const buf = new Uint8Array ( await response . arrayBuffer ( ) ) ; if ( buf . length === 0 ) { responseBodyType = 'empty' ; responseBodyValue = undefined ; } else if ( saidContentType === CONTENT_TYPE_JSON ) { responseBodyType = 'json' ; responseBodyValue = toJson ( buf ) ; } else if ( saidContentType ?. includes ( CONTENT_TYPE_HTML ) ) { responseBodyType = 'html' ; responseBodyValue = toStr ( buf ) ; } else if ( expectedProtobufMsg ) { let msgToUse = expectedProtobufMsg ; if ( ! response . ok && expectedProtobufMsgOnError ) { msgToUse = expectedProtobufMsgOnError ; } const res = await deserializeProtobuf ( buf , msgToUse , protoCtx ) ; switch ( res . tag ) { case 'invalid' : if ( res . value ) { responseBodyType = 'json' ; responseBodyValue = res . value ; } else { responseBodyType = 'unknown' ; responseBodyValue = undefined ; } warning = res . error ; break ; case 'valid' : responseBodyType = 'protobuf' ; responseBodyValue = res . value ; break ; } } return { statusCode : response . status , headers : responseHeaders , body : { type : responseBodyType , value : responseBodyValue , bodySize : buf . length , } , warning , time : dt , } ; } function toStr ( buf ) { try { return new TextDecoder ( ) . decode ( buf ) ; } catch ( err ) { throw new Error ( 'Error occurred while decoding body to string:\n' + err . message ) ; } } function toJson ( buf ) { const str = toStr ( buf ) ; try { return JSON . stringify ( JSON . parse ( str ) , null , 2 ) ; } catch ( err ) { throw new Error ( 'Error occurred while parsing json:\n' + err . message + '\nGiven JSON:\n' + str ) ; } }