/* Ċ Ġ* ĠCopyright Ġ 2 0 1 9 - 2 0 2 1 ĠDavid ĠBl anc Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġfr . s peek ha . http mock er . ktor . io Ċ Ċ import Ġfr . s peek ha . http mock er . io . HttpRequest Ċ import Ġfr . s peek ha . http mock er . io . MediaType Ċ import Ġfr . s peek ha . http mock er . message For Http Code Ċ import Ġfr . s peek ha . http mock er . model . Named Parameter Ċ import Ġfr . s peek ha . http mock er . model . Response Descriptor Ċ import Ġio . ktor . client . request . HttpRequest Data Ċ import Ġio . ktor . client . request . HttpResponse Data Ċ import Ġio . ktor . client . utils . Empty Content Ċ import Ġio . ktor . content . ByteArray Content Ċ import Ġio . ktor . content . Text Content Ċ import Ġio . ktor . http . ContentType Ċ import Ġio . ktor . http . Headers Ċ import Ġio . ktor . http . HttpHeaders Ċ import Ġio . ktor . http . Http Protocol Version Ċ import Ġio . ktor . http . HttpStatusCode Ċ import Ġio . ktor . http . Url Ċ import Ġio . ktor . http . headers Of Ċ import Ġio . ktor . util . date . GMT Date Ċ import Ġio . ktor . utils . io . Byte Read Channel Ċ import Ġio . ktor . utils . io . core . toByteArray Ċ import Ġkotlinx . coroutines . Coroutine Dispatcher Ċ import Ġkotlinx . coroutines . Job Ċ import Ġkotlinx . coroutines . with Context Ċ Ċ internal Ġexpect Ġval Ġdispatcher IO : ĠCor outine Dispatcher Ċ Ċ internal Ġfun ĠHttpResponse Data . to Descriptor ( url : ĠUrl ) Ġ= ĠResponse Descriptor ( ĊĠĠĠ Ġcode Ġ= ĠstatusCode . value , ĊĠĠĠ Ġbody File Ġ= Ġurl . to Body File () Ġ+ Ġ"_ body _", ĊĠĠĠ Ġheaders Ġ= Ġheaders . to Model () Ċ ) Ċ Ċ internal Ġfun Ġmap Request ( request : ĠHttpRequest Data ) Ġ= Ġrequest . to Model () Ċ Ċ internal Ġfun ĠHttpRequest Data . to Model (): ĠHttpRequest Ġ= ĠHttpRequest ( ĊĠĠĠ Ġmethod Ġ= Ġmethod . value , ĊĠĠĠ Ġscheme Ġ= Ġurl . protocol . name , ĊĠĠĠ Ġhost Ġ= Ġurl . host , ĊĠĠĠ Ġport Ġ= Ġurl . port , ĊĠĠĠ Ġpath Ġ= Ġurl . encoded Path , ĊĠĠĠ Ġparams Ġ= Ġurl . parameters . entries () ĊĠĠĠĠĠĠĠ Ġ. flatMap Ġ{ Ġ( key , Ġvalues ) Ġ-> Ġvalues . map Ġ{ ĠNamed Parameter ( key , Ġit ) Ġ} Ġ}, ĊĠĠĠ Ġheaders Ġ= Ġheaders . to Model (), ĊĠĠĠ Ġbody Ġ= Ġread Body () Ċ ) Ċ Ċ internal Ġfun ĠResponse Descriptor . to K tor Request () Ġ= ĠHttpResponse Data ( ĊĠĠĠ ĠstatusCode Ġ= ĠHttpStatusCode ( code , Ġmessage For Http Code ( code )), ĊĠĠĠ Ġrequest Time Ġ= ĠGMT Date (), ĊĠĠĠ Ġheaders Ġ= Ġbuild Headers (), ĊĠĠĠ Ġversion Ġ= ĠHttp Protocol Version . HTTP _ 2 _ 0 , ĊĠĠĠ Ġbody Ġ= ĠByte Read Channel ( body ), ĊĠĠĠ Ġcall Context Ġ= ĠJob () Ġ+ Ġdispatcher IO Ċ ) Ċ Ċ private Ġfun ĠResponse Descriptor . build Headers () Ġ= Ġheaders Of (* build Header List (). to Typed Array ()) Ċ Ċ private Ġfun ĠResponse Descriptor . build Header List () Ġ= Ġheaders ĊĠĠĠ Ġ. groupBy Ġ{ Ġit . name Ġ} ĊĠĠĠ Ġ. map Values Ġ{ Ġit . value . map NotNull Ġ{ Ġheader Ġ-> Ġheader . value Ġ} Ġ} ĊĠĠĠ Ġ. entries ĊĠĠĠ Ġ. map Ġ{ Ġit . key Ġto Ġit . value Ġ} Ġ+ Ġ( HttpHeaders . ContentType Ġto ĠlistOf ( media Type )) Ċ Ċ private Ġfun ĠHeaders . to Model () Ġ= Ġentries (). flatMap Ġ{ Ġ( key , Ġvalues ) Ġ-> ĊĠĠĠ Ġvalues . map Ġ{ Ġvalue Ġ-> ĠNamed Parameter ( key , Ġvalue ) Ġ} Ċ } Ċ Ċ private Ġfun ĠHttpRequest Data . read Body () Ġ= Ġwhen Ġ( val Ġcontent Ġ= Ġbody ) Ġ{ ĊĠĠĠ Ġis ĠEmpty Content Ġ-> Ġnull ĊĠĠĠ Ġis ĠText Content Ġ-> Ġcontent . text ĊĠĠĠ Ġis ĠByteArray Content Ġ-> Ġcontent . bytes (). content ToString () ĊĠĠĠ Ġelse Ġ-> Ġbody . toString () Ċ } Ċ Ċ internal Ġfun ĠUrl . to Body File (): ĠString Ġ{ ĊĠĠĠ Ġval Ġlast Segment Ġ= Ġencoded Path . substring After Last ('/') ĊĠĠĠ Ġreturn Ġlast Segment . take Unless Ġ{ Ġit . isBlank () Ġ} Ġ?: Ġ" index " Ċ } Ċ Ċ internal Ġfun ĠHttpResponse Data . with Body ( body : ĠByteArray ?) Ġ= ĠHttpResponse Data ( ĊĠĠĠ ĠstatusCode Ġ= ĠstatusCode , ĊĠĠĠ Ġrequest Time Ġ= Ġrequest Time , ĊĠĠĠ Ġheaders Ġ= Ġheaders , ĊĠĠĠ Ġversion Ġ= Ġversion , ĊĠĠĠ Ġbody Ġ= Ġbody ?. let Ġ{ ĠByte Read Channel ( it , Ġ 0 , Ġit . size ) Ġ} Ġ?: ĠByte Read Channel . Empty , ĊĠĠĠ Ġcall Context Ġ= Ġcall Context Ċ ) Ċ Ċ internal Ġfun ĠHttpResponse Data . get MediaType (): ĠMediaType ? Ġ{ ĊĠĠĠ Ġval ĠcontentType Ġ= Ġheaders [ HttpHeaders . ContentType ]?. let Ġ{ ĠContentType . parse ( it ) Ġ} ĊĠĠĠ Ġreturn ĠcontentType ?. run Ġ{ ĠMediaType ( contentType . contentType , ĠcontentType . content Subtype ) Ġ} Ċ } Ċ Ċ internal Ġsuspend Ġfun ĠHttpResponse Data . read Body (): ĠByteArray Ġ= Ġwhen Ġ( val Ġcontent Ġ= Ġbody ) Ġ{ ĊĠĠĠ Ġis ĠByte Read Channel Ġ-> Ġcontent . read Bytes () ĊĠĠĠ Ġelse Ġ-> Ġcontent . toString (). toByteArray () Ċ } Ċ Ċ private Ġconst Ġval ĠREAD _ CHANNEL _ CH UN KS Ġ= Ġ 1 0 2 4 Ċ Ċ internal Ġsuspend Ġfun ĠByte Read Channel . read Bytes (): ĠByteArray Ġ{ ĊĠĠĠ Ġval Ġdata Ġ= Ġmutable ListOf < ByteArray >() ĊĠĠĠ Ġwhile Ġ(! is Closed For Read ) Ġ{ ĊĠĠĠĠĠĠĠ Ġtransfer Chunk ()?. let Ġ{ Ġdata Ġ+= Ġit Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn ĠByteArray ( data . sum Of Ġ{ Ġit . size Ġ}) Ġ{ ĊĠĠĠĠĠĠĠ Ġdata [ it Ġ/ ĠREAD _ CHANNEL _ CH UN KS ][ it Ġ% ĠREAD _ CHANNEL _ CH UN KS ] ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġsuspend Ġfun ĠByte Read Channel . transfer Chunk (): ĠByteArray ? Ġ= Ġwith Context ( dispatcher IO ) Ġ{ ĊĠĠĠ Ġval Ġbuffer Ġ= ĠByteArray ( READ _ CHANNEL _ CH UN KS ) ĊĠĠĠ Ġwhen Ġ( val Ġlength Ġ= Ġread Available ( buffer , Ġ 0 , ĠREAD _ CHANNEL _ CH UN KS )) Ġ{ ĊĠĠĠĠĠĠĠ ĠREAD _ CHANNEL _ CH UN KS Ġ-> Ġbuffer ĊĠĠĠĠĠĠĠ Ġin Ġ 1 Ġuntil ĠREAD _ CHANNEL _ CH UN KS Ġ-> Ġbuffer . copyOf Range ( 0 , Ġlength ) ĊĠĠĠĠĠĠĠ Ġelse Ġ-> Ġnull ĊĠĠĠ Ġ} Ċ } Ċ